diff options
300 files changed, 14632 insertions, 3208 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py index cf56850df..99cc02185 100644 --- a/build_scripts/main.py +++ b/build_scripts/main.py @@ -74,10 +74,12 @@ def get_package_version(): final_version = "{}.{}.{}".format( d['major_version'], d['minor_version'], d['patch_version']) - pre_release_version_type = d['pre_release_version_type'] + release_version_type = d['release_version_type'] pre_release_version = d['pre_release_version'] - if pre_release_version and pre_release_version_type: - final_version += pre_release_version_type + pre_release_version + if pre_release_version and release_version_type: + final_version += release_version_type + pre_release_version + if release_version_type.startswith("comm"): + final_version += "." + release_version_type # Add the current timestamp to the version number, to suggest it # is a development snapshot build. @@ -354,7 +356,7 @@ class PysideInstall(_install): def run(self): _install.run(self) - print('*** Install completed ({}s)'.format(elapsed())) + print('--- Install completed ({}s)'.format(elapsed())) class PysideDevelop(_develop): @@ -735,7 +737,7 @@ class PysideBuild(_build): _build.run(self) else: log.info("Skipped preparing and building packages.") - print('*** Build completed ({}s)'.format(elapsed())) + print('--- Build completed ({}s)'.format(elapsed())) def log_pre_build_info(self): if config.is_internal_shiboken_generator_build_and_part_of_top_level_all(): @@ -746,16 +748,16 @@ class PysideBuild(_build): setuptools_install_prefix = OPTION["FINAL_INSTALL_PREFIX"] log.info("=" * 30) log.info("Package version: {}".format(get_package_version())) - log.info("Build type: {}".format(self.build_type)) + log.info("Build type: {}".format(self.build_type)) log.info("Build tests: {}".format(self.build_tests)) log.info("-" * 3) - log.info("Make path: {}".format(self.make_path)) + log.info("Make path: {}".format(self.make_path)) log.info("Make generator: {}".format(self.make_generator)) - log.info("Make jobs: {}".format(OPTION["JOBS"])) + log.info("Make jobs: {}".format(OPTION["JOBS"])) log.info("-" * 3) - log.info("setup.py directory: {}".format(self.script_dir)) + log.info("setup.py directory: {}".format(self.script_dir)) log.info("Build scripts directory: {}".format(build_scripts_dir)) - log.info("Sources directory: {}".format(self.sources_dir)) + log.info("Sources directory: {}".format(self.sources_dir)) log.info(dedent(""" Building {st_package_name} will create and touch directories in the following order: @@ -765,9 +767,9 @@ class PysideBuild(_build): setuptools install directory (usually path-installed-python/lib/python*/site-packages/*) """).format(st_package_name=config.package_name())) - log.info("make build directory: {}".format(self.build_dir)) + log.info("make build directory: {}".format(self.build_dir)) log.info("make install directory: {}".format(self.install_dir)) - log.info("setuptools build directory: {}".format(self.st_build_dir)) + log.info("setuptools build directory: {}".format(self.st_build_dir)) log.info("setuptools install directory: {}".format(setuptools_install_prefix)) log.info(dedent(""" make-installed site-packages directory: {} @@ -777,15 +779,15 @@ class PysideBuild(_build): self.site_packages_dir)) log.info("-" * 3) log.info("Python executable: {}".format(self.py_executable)) - log.info("Python includes: {}".format(self.py_include_dir)) - log.info("Python library: {}".format(self.py_library)) - log.info("Python prefix: {}".format(self.py_prefix)) - log.info("Python scripts: {}".format(self.py_scripts_dir)) + log.info("Python includes: {}".format(self.py_include_dir)) + log.info("Python library: {}".format(self.py_library)) + log.info("Python prefix: {}".format(self.py_prefix)) + log.info("Python scripts: {}".format(self.py_scripts_dir)) log.info("-" * 3) - log.info("Qt qmake: {}".format(self.qtinfo.qmake_command)) + log.info("Qt qmake: {}".format(self.qtinfo.qmake_command)) log.info("Qt version: {}".format(self.qtinfo.version)) - log.info("Qt bins: {}".format(self.qtinfo.bins_dir)) - log.info("Qt docs: {}".format(self.qtinfo.docs_dir)) + log.info("Qt bins: {}".format(self.qtinfo.bins_dir)) + log.info("Qt docs: {}".format(self.qtinfo.docs_dir)) log.info("Qt plugins: {}".format(self.qtinfo.plugins_dir)) log.info("-" * 3) if sys.platform == 'win32': @@ -1057,6 +1059,13 @@ class PysideBuild(_build): cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format(deployment_target)) os.environ['MACOSX_DEPLOYMENT_TARGET'] = deployment_target + if OPTION["DOC_BUILD_ONLINE"]: + log.info("Output format will be HTML") + cmake_cmd.append("-DDOC_OUTPUT_FORMAT=html") + else: + log.info("Output format will be qthelp") + cmake_cmd.append("-DDOC_OUTPUT_FORMAT=qthelp") + if not OPTION["SKIP_CMAKE"]: log.info("Configuring module {} ({})...".format(extension, module_src_dir)) if run_process(cmake_cmd) != 0: @@ -1065,7 +1074,7 @@ class PysideBuild(_build): log.info("Reusing old configuration for module {} ({})...".format( extension, module_src_dir)) - log.info("Compiling module {}...".format(extension)) + log.info("-- Compiling module {}...".format(extension)) cmd_make = [self.make_path] if OPTION["JOBS"]: cmd_make.append(OPTION["JOBS"]) diff --git a/build_scripts/options.py b/build_scripts/options.py index 4229a2c10..db2a7e367 100644 --- a/build_scripts/options.py +++ b/build_scripts/options.py @@ -182,6 +182,8 @@ OPTION = { # This is used automatically by distutils.command.install object, to # specify the final installation location. "FINAL_INSTALL_PREFIX": option_value("prefix", remove=False), + # This is used to identify the template for doc builds + "DOC_BUILD_ONLINE": has_option("doc-build-online"), } _deprecated_option_jobs = option_value('jobs') if _deprecated_option_jobs: diff --git a/build_scripts/platforms/windows_desktop.py b/build_scripts/platforms/windows_desktop.py index 750a064b4..49c384bc7 100644 --- a/build_scripts/platforms/windows_desktop.py +++ b/build_scripts/platforms/windows_desktop.py @@ -251,7 +251,8 @@ def copy_msvc_redist_files(vars, redist_target_path): "vcamp140.dll", "vccorlib140.dll", "vcomp140.dll", - "vcruntime140.dll" + "vcruntime140.dll", + "vcruntime140_1.dll" ] # Make a directory where the files should be extracted. @@ -262,9 +263,9 @@ def copy_msvc_redist_files(vars, redist_target_path): in_coin = os.environ.get('COIN_LAUNCH_PARAMETERS', None) if in_coin is not None: redist_url = "http://download.qt.io/development_releases/prebuilt/vcredist/" - zip_file = "pyside_qt_deps_64.7z" + zip_file = "pyside_qt_deps_64_2019.7z" if "{target_arch}".format(**vars) == "32": - zip_file = "pyside_qt_deps_32.7z" + zip_file = "pyside_qt_deps_32_2019.7z" download_and_extract_7z(redist_url + zip_file, redist_target_path) else: print("Qt dependency DLLs (MSVC redist) will not be downloaded and extracted.") diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py index 1a7317e4d..b5b55fa20 100644 --- a/build_scripts/setup_runner.py +++ b/build_scripts/setup_runner.py @@ -41,6 +41,8 @@ import sys import os import textwrap +import distutils.log as log + from build_scripts.config import config from build_scripts.main import get_package_version, get_setuptools_extension_modules from build_scripts.main import cmd_class_dict @@ -49,6 +51,8 @@ from build_scripts.utils import run_process from setuptools import setup +if OPTION["VERBOSE_BUILD"]: + log.set_verbosity(1) class SetupRunner(object): def __init__(self, orig_argv): @@ -148,7 +152,7 @@ class SetupRunner(object): for cmd in self.invocations_list: cmd_as_string = " ".join(cmd) - print("\nRunning process: {}\n".format(cmd_as_string)) + log.info("\nRunning setup: {}\n".format(cmd_as_string)) exit_code = run_process(cmd) if exit_code != 0: msg = textwrap.dedent(""" diff --git a/build_scripts/utils.py b/build_scripts/utils.py index d1bc780dc..9f6d472cc 100644 --- a/build_scripts/utils.py +++ b/build_scripts/utils.py @@ -388,7 +388,7 @@ def run_process(args, initial_env=None): No output is captured. """ command = " ".join([(" " in x and '"{}"'.format(x) or x) for x in args]) - log.info("Running process in directory {}: command {}".format(os.getcwd(), command)) + log.info("In directory {}:\n\tRunning command: {}".format(os.getcwd(), command)) if initial_env is None: initial_env = os.environ diff --git a/coin/instructions/execute_license_check.yaml b/coin/instructions/execute_license_check.yaml index 3a78a0aab..51027ba7d 100644 --- a/coin/instructions/execute_license_check.yaml +++ b/coin/instructions/execute_license_check.yaml @@ -6,7 +6,7 @@ instructions: maxTimeInSeconds: 600 maxTimeBetweenOutput: 600 project: qt/qtbase - ref: 5.14 + ref: 5.15 directory: qt/qtbase userMessageOnFailure: > Could not install source archive. Please investigate why. diff --git a/coin_build_instructions.py b/coin_build_instructions.py index 5c3033b04..bfb10410c 100644 --- a/coin_build_instructions.py +++ b/coin_build_instructions.py @@ -95,9 +95,9 @@ def is_snapshot_build(): setup_script_dir, "sources", "pyside2", "pyside_version.py") d = get_python_dict(pyside_version_py) - pre_release_version_type = d['pre_release_version_type'] + release_version_type = d['release_version_type'] pre_release_version = d['pre_release_version'] - if pre_release_version or pre_release_version_type: + if pre_release_version and release_version_type: return True return False diff --git a/CHANGES.rst b/dist/changes-1.2.3 index 7deaa8bdd..7deaa8bdd 100644 --- a/CHANGES.rst +++ b/dist/changes-1.2.3 diff --git a/dist/changes-5.15.0 b/dist/changes-5.15.0 new file mode 100644 index 000000000..77c8e7d27 --- /dev/null +++ b/dist/changes-5.15.0 @@ -0,0 +1,49 @@ +Qt for Python 5.15.0 is a minor release. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qtforpython/ + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* PySide2 * +**************************************************************************** + + + - [PYSIDE-487] Add API of Qt 5.15 + - [PYSIDE-487] Add support for QSerialPort + - [PYSIDE-487] Add QtQuickControls2 + - [PYSIDE-841] example: add systray example + - [PYSIDE-841] doc: add more videos from Qt events + - [PYSIDE-841] doc: add tutorial for using qrc files + - [PYSIDE-904] libpyside: Remove deprecated API + - [PYSIDE-904] Add support for template type aliases + - [PYSIDE-957] Add a tool to dump meta objects of QObject-derived classes + - [PYSIDE-1280] Enable injecting raw code for setattro/getattro + - [PYSIDE-1309] Rename and update some snippets + +**************************************************************************** +* Shiboken2 * +**************************************************************************** + + - [PYSIDE-454] shiboken: Add a way of specifying system includes to be parsed + - [PYSIDE-454] shiboken: Handle smart pointers with const pointees + - [PYSIDE-904] libshiboken: Remove deprecated API + - [PYSIDE-957] shiboken: Fix refcounts of sbkenum + - [PYSIDE-990] shiboken: Handle inline namespaces + - [PYSIDE-1024] shiboken: Make it possible to specify smartpointer instantiations + - [PYSIDE-1074] shiboken: Fix classes in hidden namespaces + - [PYSIDE-1188] shiboken: Fix shared pointer return value in virtual function + - [PYSIDE-1265] shiboken: Introduce a separate logging category for documentation generation + - [PYSIDE-1265] shiboken: Change debug messages to use qCInfo and remove some messages + - [PYSIDE-1267] shiboken: Allow for parsing headers under system include paths + - [PYSIDE-1296] shiboken: Support non-type template parameters in functions + diff --git a/examples/charts/charts.pyproject b/examples/charts/charts.pyproject index a4e6c01c1..15a48a3a1 100644 --- a/examples/charts/charts.pyproject +++ b/examples/charts/charts.pyproject @@ -1,3 +1,5 @@ { - "files": ["percentbarchart.py", "donutbreakdown.py", "legend.py", "nesteddonuts.py", "modeldata.py", "lineandbar.py", "memoryusage.py", "callout.py", "audio.py"] + "files": ["percentbarchart.py", "donutbreakdown.py", "legend.py", "nesteddonuts.py", + "modeldata.py", "lineandbar.py", "memoryusage.py", "callout.py", "audio.py", + "linechart.py", "logvalueaxis.py", "piechart.py", "temperaturerecords.py"] } diff --git a/examples/charts/linechart.py b/examples/charts/linechart.py new file mode 100644 index 000000000..98d17b35c --- /dev/null +++ b/examples/charts/linechart.py @@ -0,0 +1,84 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the linechart example from Qt v5.x""" + +import sys +from PySide2.QtCore import QPointF +from PySide2.QtGui import QPainter +from PySide2.QtWidgets import QMainWindow, QApplication +from PySide2.QtCharts import QtCharts + + +class TestChart(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + self.series = QtCharts.QLineSeries() + self.series.append(0, 6) + self.series.append(2, 4) + self.series.append(3, 8) + self.series.append(7, 4) + self.series.append(10, 5) + self.series.append(QPointF(11, 1)) + self.series.append(QPointF(13, 3)) + self.series.append(QPointF(17, 6)) + self.series.append(QPointF(18, 3)) + self.series.append(QPointF(20, 2)) + + self.chart = QtCharts.QChart() + self.chart.legend().hide() + self.chart.addSeries(self.series) + self.chart.createDefaultAxes() + self.chart.setTitle("Simple line chart example") + + self.chartView = QtCharts.QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(440, 300) + sys.exit(app.exec_()) diff --git a/examples/charts/logvalueaxis.py b/examples/charts/logvalueaxis.py new file mode 100644 index 000000000..7fb5604cd --- /dev/null +++ b/examples/charts/logvalueaxis.py @@ -0,0 +1,94 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the Logarithmic Axis Example from Qt v5.x""" + + + +import sys +from PySide2.QtCore import Qt, QPointF +from PySide2.QtGui import QPainter +from PySide2.QtWidgets import QMainWindow, QApplication +from PySide2.QtCharts import QtCharts + + +class TestChart(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + self.series = QtCharts.QLineSeries() + self.series.append([ + QPointF(1.0, 1.0), QPointF(2.0, 73.0), QPointF(3.0, 268.0), + QPointF(4.0, 17.0), QPointF(5.0, 4325.0), QPointF(6.0, 723.0)]) + + self.chart = QtCharts.QChart() + self.chart.addSeries(self.series) + self.chart.legend().hide() + self.chart.setTitle("Logarithmic axis example") + + self.axisX = QtCharts.QValueAxis() + self.axisX.setTitleText("Data point") + self.axisX.setLabelFormat("%i") + self.axisX.setTickCount(self.series.count()) + self.chart.addAxis(self.axisX, Qt.AlignBottom) + self.series.attachAxis(self.axisX) + + self.axisY = QtCharts.QLogValueAxis() + self.axisY.setTitleText("Values") + self.axisY.setLabelFormat("%g") + self.axisY.setBase(8.0) + self.axisY.setMinorTickCount(-1) + self.chart.addAxis(self.axisY, Qt.AlignLeft) + self.series.attachAxis(self.axisY) + + self.chartView = QtCharts.QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(800, 600) + + sys.exit(app.exec_()) diff --git a/examples/charts/piechart.py b/examples/charts/piechart.py new file mode 100644 index 000000000..820da8b91 --- /dev/null +++ b/examples/charts/piechart.py @@ -0,0 +1,87 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the Pie Chart Example from Qt v5.x""" + +import sys +from PySide2.QtCore import Qt +from PySide2.QtGui import QPainter, QPen +from PySide2.QtWidgets import QMainWindow, QApplication +from PySide2.QtCharts import QtCharts + + +class TestChart(QMainWindow): + + def __init__(self): + QMainWindow.__init__(self) + + self.series = QtCharts.QPieSeries() + + self.series.append('Jane', 1) + self.series.append('Joe', 2) + self.series.append('Andy', 3) + self.series.append('Barbara', 4) + self.series.append('Axel', 5) + + self.slice = self.series.slices()[1] + self.slice.setExploded() + self.slice.setLabelVisible() + self.slice.setPen(QPen(Qt.darkGreen, 2)) + self.slice.setBrush(Qt.green) + + self.chart = QtCharts.QChart() + self.chart.addSeries(self.series) + self.chart.setTitle('Simple piechart example') + self.chart.legend().hide() + + self.chartView = QtCharts.QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(440, 300) + + sys.exit(app.exec_()) diff --git a/examples/charts/qmlpolarchart/View1.qml b/examples/charts/qmlpolarchart/View1.qml new file mode 100644 index 000000000..ad17fec6b --- /dev/null +++ b/examples/charts/qmlpolarchart/View1.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtCharts 2.0 + +Item { + anchors.fill: parent + //![1] + PolarChartView { + title: "Two Series, Common Axes" + anchors.fill: parent + legend.visible: false + antialiasing: true + + ValueAxis { + id: axisAngular + min: 0 + max: 20 + tickCount: 9 + } + + ValueAxis { + id: axisRadial + min: -0.5 + max: 1.5 + } + + SplineSeries { + id: series1 + axisAngular: axisAngular + axisRadial: axisRadial + pointsVisible: true + } + + ScatterSeries { + id: series2 + axisAngular: axisAngular + axisRadial: axisRadial + markerSize: 10 + } + } + + // Add data dynamically to the series + Component.onCompleted: { + for (var i = 0; i <= 20; i++) { + series1.append(i, Math.random()); + series2.append(i, Math.random()); + } + } + //![1] +} diff --git a/examples/charts/qmlpolarchart/View2.qml b/examples/charts/qmlpolarchart/View2.qml new file mode 100644 index 000000000..7f241c3e7 --- /dev/null +++ b/examples/charts/qmlpolarchart/View2.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtCharts 2.0 + +Item { + anchors.fill: parent + + //![1] + PolarChartView { + title: "Historical Area Series" + anchors.fill: parent + legend.visible: false + antialiasing: true + + DateTimeAxis { + id: axis1 + format: "yyyy MMM" + tickCount: 13 + } + ValueAxis { + id: axis2 + } + LineSeries { + id: lowerLine + axisAngular: axis1 + axisRadial: axis2 + + // Please note that month in JavaScript months are zero based, so 2 means March + XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 15 } + XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 35 } + XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 50 } + XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 75 } + XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 102 } + XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 132 } + XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 100 } + XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 120 } + XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 140 } + XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 150 } + } + LineSeries { + id: upperLine + axisAngular: axis1 + axisRadial: axis2 + + // Please note that month in JavaScript months are zero based, so 2 means March + XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 30 } + XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 55 } + XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 80 } + XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 105 } + XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 125 } + XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 160 } + XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 140 } + XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 140 } + XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 170 } + XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 200 } + } + AreaSeries { + axisAngular: axis1 + axisRadial: axis2 + lowerSeries: lowerLine + upperSeries: upperLine + } + } + // DateTimeAxis is based on QDateTimes so we must convert our JavaScript dates to + // milliseconds since epoch to make them match the DateTimeAxis values + function toMsecsSinceEpoch(date) { + var msecs = date.getTime(); + return msecs; + } + //![1] +} diff --git a/examples/charts/qmlpolarchart/View3.qml b/examples/charts/qmlpolarchart/View3.qml new file mode 100644 index 000000000..5695a891f --- /dev/null +++ b/examples/charts/qmlpolarchart/View3.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtCharts 2.0 + +Item { + anchors.fill: parent + + //![1] + PolarChartView { + title: "Numerical Data for Dummies" + anchors.fill: parent + legend.visible: false + antialiasing: true + + LineSeries { + axisRadial: CategoryAxis { + min: 0 + max: 30 + CategoryRange { + label: "critical" + endValue: 2 + } + CategoryRange { + label: "low" + endValue: 7 + } + CategoryRange { + label: "normal" + endValue: 12 + } + CategoryRange { + label: "high" + endValue: 18 + } + CategoryRange { + label: "extremely high" + endValue: 30 + } + } + + axisAngular: ValueAxis { + tickCount: 13 + } + + XYPoint { x: 0; y: 4.3 } + XYPoint { x: 1; y: 4.1 } + XYPoint { x: 2; y: 4.7 } + XYPoint { x: 3; y: 3.9 } + XYPoint { x: 4; y: 5.2 } + XYPoint { x: 5; y: 5.3 } + XYPoint { x: 6; y: 6.1 } + XYPoint { x: 7; y: 7.7 } + XYPoint { x: 8; y: 12.9 } + XYPoint { x: 9; y: 19.2 } + } + } + //![1] +} diff --git a/examples/charts/qmlpolarchart/main.qml b/examples/charts/qmlpolarchart/main.qml new file mode 100644 index 000000000..ed7a810c6 --- /dev/null +++ b/examples/charts/qmlpolarchart/main.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + width: 800 + height: 600 + property bool sourceLoaded: false + + ListView { + id: root + focus: true + anchors.fill: parent + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.StrictlyEnforceRange + highlightMoveDuration: 250 + orientation: ListView.Horizontal + boundsBehavior: Flickable.StopAtBounds + + onCurrentIndexChanged: { + if (infoText.opacity > 0.0) { + if (sourceLoaded) + infoText.opacity = 0.0; + else if (currentIndex != 0) + currentIndex = 0; + } + } + + model: ListModel { + ListElement {component: "View1.qml"} + ListElement {component: "View2.qml"} + ListElement {component: "View3.qml"} + } + + delegate: Loader { + width: root.width + height: root.height + + source: component + asynchronous: true + + onLoaded: sourceLoaded = true + } + } + + Rectangle { + id: infoText + anchors.centerIn: parent + width: parent.width + height: 40 + color: "black" + Text { + color: "white" + anchors.centerIn: parent + text: "You can navigate between views using swipe or arrow keys" + } + + Behavior on opacity { + NumberAnimation { duration: 400 } + } + } +} diff --git a/examples/charts/qmlpolarchart/qmlpolarchart.py b/examples/charts/qmlpolarchart/qmlpolarchart.py new file mode 100644 index 000000000..4398169b0 --- /dev/null +++ b/examples/charts/qmlpolarchart/qmlpolarchart.py @@ -0,0 +1,63 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the QML Polar Chart Example from Qt v5.x""" + +import sys +import os +from PySide2.QtQuick import QQuickView +from PySide2.QtCore import Qt, QUrl +from PySide2.QtWidgets import QApplication, QMainWindow + + +if __name__ == '__main__': + app = QApplication(sys.argv) + viewer = QQuickView() + + viewer.engine().addImportPath(os.path.dirname(__file__)) + viewer.engine().quit.connect(viewer.close) + + viewer.setTitle = "QML Polar Chart" + qmlFile = os.path.join(os.path.dirname(__file__), 'main.qml') + viewer.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile))) + viewer.setResizeMode(QQuickView.SizeRootObjectToView) + viewer.show() + + sys.exit(app.exec_()) diff --git a/examples/charts/qmlpolarchart/qmlpolarchart.pyproject b/examples/charts/qmlpolarchart/qmlpolarchart.pyproject new file mode 100644 index 000000000..6c18b1f43 --- /dev/null +++ b/examples/charts/qmlpolarchart/qmlpolarchart.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["View1.qml", "View1.qml", "View2.qml", "View3.qml", "main.qml", "qmlpolarchart.py"] +} diff --git a/examples/charts/temperaturerecords.py b/examples/charts/temperaturerecords.py new file mode 100644 index 000000000..dfd4dd67c --- /dev/null +++ b/examples/charts/temperaturerecords.py @@ -0,0 +1,95 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the Temperature Records example from Qt v5.x""" + +import sys +from PySide2.QtCore import Qt +from PySide2.QtGui import QPainter +from PySide2.QtWidgets import QMainWindow, QApplication +from PySide2.QtCharts import QtCharts + + +class MainWindow(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + low = QtCharts.QBarSet("Min") + high = QtCharts.QBarSet("Max") + low.append([-52, -50, -45.3, -37.0, -25.6, -8.0, + -6.0, -11.8, -19.7, -32.8, -43.0, -48.0]) + high.append([11.9, 12.8, 18.5, 26.5, 32.0, 34.8, + 38.2, 34.8, 29.8, 20.4, 15.1, 11.8]) + + series = QtCharts.QStackedBarSeries() + series.append(low) + series.append(high) + + chart = QtCharts.QChart() + chart.addSeries(series) + chart.setTitle("Temperature records in celcius") + chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations) + + categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"] + axisX = QtCharts.QBarCategoryAxis() + axisX.append(categories) + axisX.setTitleText("Month") + chart.addAxis(axisX, Qt.AlignBottom) + axisY = QtCharts.QValueAxis() + axisY.setRange(-52, 52) + axisY.setTitleText("Temperature [°C]") + chart.addAxis(axisY, Qt.AlignLeft) + series.attachAxis(axisX) + series.attachAxis(axisY) + + chart.legend().setVisible(True) + chart.legend().setAlignment(Qt.AlignBottom) + + chart_view = QtCharts.QChartView(chart) + chart_view.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(chart_view) + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = MainWindow() + w.resize(600, 300) + w.show() + sys.exit(app.exec_()) diff --git a/examples/declarative/textproperties/main.py b/examples/declarative/textproperties/main.py index 8da443edc..2f9b987d0 100644 --- a/examples/declarative/textproperties/main.py +++ b/examples/declarative/textproperties/main.py @@ -44,6 +44,7 @@ from os.path import abspath, dirname, join from PySide2.QtCore import QObject, Slot from PySide2.QtGui import QGuiApplication from PySide2.QtQml import QQmlApplicationEngine +from PySide2.QtQuickControls2 import QQuickStyle class Bridge(QObject): @@ -90,8 +91,8 @@ class Bridge(QObject): if __name__ == '__main__': - sys.argv += ['--style', 'material'] app = QGuiApplication(sys.argv) + QQuickStyle.setStyle("Material") engine = QQmlApplicationEngine() # Instance of the Python object diff --git a/examples/scriptableapplication/mainwindow.cpp b/examples/scriptableapplication/mainwindow.cpp index 15504cb6e..ef4a2f2e0 100644 --- a/examples/scriptableapplication/mainwindow.cpp +++ b/examples/scriptableapplication/mainwindow.cpp @@ -114,7 +114,7 @@ MainWindow::MainWindow() void MainWindow::slotRunScript() { - const QStringList script = m_scriptEdit->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts); + const QStringList script = m_scriptEdit->toPlainText().trimmed().split(QLatin1Char('\n'), Qt::SkipEmptyParts); if (!script.isEmpty()) runScript(script); } diff --git a/examples/widgets/gallery/gallery.pyproject b/examples/widgets/gallery/gallery.pyproject new file mode 100644 index 000000000..635e123b0 --- /dev/null +++ b/examples/widgets/gallery/gallery.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["main.py", "widgetgallery.py"] +} diff --git a/examples/widgets/gallery/main.py b/examples/widgets/gallery/main.py new file mode 100644 index 000000000..11f19201b --- /dev/null +++ b/examples/widgets/gallery/main.py @@ -0,0 +1,56 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the widgets/gallery example from Qt v5.15""" + +import sys + +from PySide2.QtCore import QCoreApplication, Qt +from PySide2.QtWidgets import QApplication +from widgetgallery import WidgetGallery + + +if __name__ == '__main__': + QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) + QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) + app = QApplication() + gallery = WidgetGallery() + gallery.show() + sys.exit(app.exec_()) diff --git a/examples/widgets/gallery/widgetgallery.py b/examples/widgets/gallery/widgetgallery.py new file mode 100644 index 000000000..a06ac2e20 --- /dev/null +++ b/examples/widgets/gallery/widgetgallery.py @@ -0,0 +1,429 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +import sys + +from PySide2.QtWidgets import * +from PySide2.QtGui import (QCursor, QDesktopServices, QGuiApplication, QIcon, + QKeySequence, QStandardItem, QStandardItemModel, + QScreen, QWindow) +from PySide2.QtCore import (QDateTime, QDir, QLibraryInfo, QMetaObject, + QSysInfo, QTextStream, QTimer, Qt, qVersion) + + +POEM = """Twinkle, twinkle, little star, +How I wonder what you are. +Up above the world so high, +Like a diamond in the sky. +Twinkle, twinkle, little star, +How I wonder what you arenot""" + +DIR_OPEN_ICON = ":/qt-project.org/styles/commonstyle/images/diropen-128.png" + +COMPUTER_ICON = ":/qt-project.org/styles/commonstyle/images/computer-32.png" + +SYSTEMINFO = """<html><head/><body> +<h3>Python</h3><p>{}</p> +<h3>Qt Build</h3><p>{}</p> +<h3>Operating System</h3><p>{}</p> +<h3>Screens</h3> +{} +</body></html>""" + + +def class_name(o): + return o.metaObject().className() + + +def help_url(page): + """Build a Qt help URL from the page name""" + major_version = qVersion().split('.')[0] + return "https://doc.qt.io/qt-{}/{}.html".format(major_version, page) + + +def launch_help(widget): + """Launch a widget's help page""" + url = help_url(class_name(widget).lower()) + QDesktopServices.openUrl(url) + + +def launch_module_help(): + QDesktopServices.openUrl(help_url("qtwidgets-index")) + + +def init_widget(w, name): + """Init a widget for the gallery, give it a tooltip showing the + class name""" + w.setObjectName(name) + w.setToolTip(class_name(w)) + + +def style_names(): + """Return a list of styles, default platform style first""" + default_style_name = QApplication.style().objectName().lower() + result = [] + for style in QStyleFactory.keys(): + if style.lower() == default_style_name: + result.insert(0, style) + else: + result.append(style) + return result + + +def embed_into_hbox_layout(w, margin=5): + """Embed a widget into a layout to give it a frame""" + result = QWidget() + layout = QHBoxLayout(result) + layout.setContentsMargins(margin, margin, margin, margin) + layout.addWidget(w) + return result + + +def format_geometry(rect): + """Format a geometry as a X11 geometry specification""" + return "{}x{}{:+d}{:+d}".format(rect.width(), rect.height(), + rect.x(), rect.y()) + + +def screen_info(widget): + """Format information on the screens""" + policy = QGuiApplication.highDpiScaleFactorRoundingPolicy() + policy_string = str(policy).split('.')[-1] + result = "<p>High DPI scale factor rounding policy: {}</p><ol>".format(policy_string) + for screen in QGuiApplication.screens(): + current = screen == widget.screen() + result += "<li>" + if current: + result += "<i>" + result += '"{}" {} {}DPI, DPR={}'.format(screen.name(), + format_geometry(screen.geometry()), + int(screen.logicalDotsPerInchX()), + screen.devicePixelRatio()) + if current: + result += "</i>" + result += "</li>" + result += "</ol>" + return result + + +class WidgetGallery(QDialog): + """Dialog displaying a gallery of Qt Widgets""" + + def __init__(self): + super(WidgetGallery, self).__init__() + + self._progress_bar = self.create_progress_bar() + + self._style_combobox = QComboBox() + init_widget(self._style_combobox, "styleComboBox") + self._style_combobox.addItems(style_names()) + + style_label = QLabel("Style:") + init_widget(style_label, "style_label") + style_label.setBuddy(self._style_combobox) + + help_label = QLabel("Press F1 over a widget to see Documentation") + init_widget(help_label, "help_label") + + disable_widgets_checkbox = QCheckBox("Disable widgets") + init_widget(disable_widgets_checkbox, "disable_widgets_checkbox") + + buttons_groupbox = self.create_buttons_groupbox() + itemview_tabwidget = self.create_itemview_tabwidget() + simple_input_widgets_groupbox = self.create_simple_inputwidgets_groupbox() + text_toolbox = self.create_text_toolbox() + + self._style_combobox.textActivated.connect(self.change_style) + disable_widgets_checkbox.toggled.connect(buttons_groupbox.setDisabled) + disable_widgets_checkbox.toggled.connect(text_toolbox.setDisabled) + disable_widgets_checkbox.toggled.connect(itemview_tabwidget.setDisabled) + disable_widgets_checkbox.toggled.connect(simple_input_widgets_groupbox.setDisabled) + + help_shortcut = QShortcut(self) + help_shortcut.setKey(QKeySequence.HelpContents) + help_shortcut.activated.connect(self.help_on_current_widget) + + top_layout = QHBoxLayout() + top_layout.addWidget(style_label) + top_layout.addWidget(self._style_combobox) + top_layout.addStretch(1) + top_layout.addWidget(help_label) + top_layout.addStretch(1) + top_layout.addWidget(disable_widgets_checkbox) + + dialog_buttonbox = QDialogButtonBox(QDialogButtonBox.Help | + QDialogButtonBox.Close) + init_widget(dialog_buttonbox, "dialogButtonBox") + dialog_buttonbox.helpRequested.connect(launch_module_help) + dialog_buttonbox.rejected.connect(self.reject) + + main_layout = QGridLayout(self) + main_layout.addLayout(top_layout, 0, 0, 1, 2) + main_layout.addWidget(buttons_groupbox, 1, 0) + main_layout.addWidget(simple_input_widgets_groupbox, 1, 1) + main_layout.addWidget(itemview_tabwidget, 2, 0) + main_layout.addWidget(text_toolbox, 2, 1) + main_layout.addWidget(self._progress_bar, 3, 0, 1, 2) + main_layout.addWidget(dialog_buttonbox, 4, 0, 1, 2) + + self.setWindowTitle("Widget Gallery Qt {}".format(qVersion())) + + def setVisible(self, visible): + super(WidgetGallery, self).setVisible(visible) + if visible: + self.windowHandle().screenChanged.connect(self.update_systeminfo) + self.update_systeminfo() + + def change_style(self, style_name): + QApplication.setStyle(QStyleFactory.create(style_name)) + + def advance_progressbar(self): + cur_val = self._progress_bar.value() + max_val = self._progress_bar.maximum() + self._progress_bar.setValue(cur_val + (max_val - cur_val) / 100) + + def create_buttons_groupbox(self): + result = QGroupBox("Buttons") + init_widget(result, "buttons_groupbox") + + default_pushbutton = QPushButton("Default Push Button") + init_widget(default_pushbutton, "default_pushbutton") + default_pushbutton.setDefault(True) + + toggle_pushbutton = QPushButton("Toggle Push Button") + init_widget(toggle_pushbutton, "toggle_pushbutton") + toggle_pushbutton.setCheckable(True) + toggle_pushbutton.setChecked(True) + + flat_pushbutton = QPushButton("Flat Push Button") + init_widget(flat_pushbutton, "flat_pushbutton") + flat_pushbutton.setFlat(True) + + toolbutton = QToolButton() + init_widget(toolbutton, "toolButton") + toolbutton.setText("Tool Button") + + menu_toolbutton = QToolButton() + init_widget(menu_toolbutton, "menuButton") + menu_toolbutton.setText("Menu Button") + tool_menu = QMenu(menu_toolbutton) + menu_toolbutton.setPopupMode(QToolButton.InstantPopup) + tool_menu.addAction("Option") + tool_menu.addSeparator() + action = tool_menu.addAction("Checkable Option") + action.setCheckable(True) + menu_toolbutton.setMenu(tool_menu) + tool_layout = QHBoxLayout() + tool_layout.addWidget(toolbutton) + tool_layout.addWidget(menu_toolbutton) + + commandlinkbutton = QCommandLinkButton("Command Link Button") + init_widget(commandlinkbutton, "commandLinkButton") + commandlinkbutton.setDescription("Description") + + button_layout = QVBoxLayout() + button_layout.addWidget(default_pushbutton) + button_layout.addWidget(toggle_pushbutton) + button_layout.addWidget(flat_pushbutton) + button_layout.addLayout(tool_layout) + button_layout.addWidget(commandlinkbutton) + button_layout.addStretch(1) + + radiobutton_1 = QRadioButton("Radio button 1") + init_widget(radiobutton_1, "radioButton1") + radiobutton_2 = QRadioButton("Radio button 2") + init_widget(radiobutton_2, "radioButton2") + radiobutton_3 = QRadioButton("Radio button 3") + init_widget(radiobutton_3, "radioButton3") + radiobutton_1.setChecked(True) + + checkbox = QCheckBox("Tri-state check box") + init_widget(checkbox, "checkBox") + checkbox.setTristate(True) + checkbox.setCheckState(Qt.PartiallyChecked) + + checkableLayout = QVBoxLayout() + checkableLayout.addWidget(radiobutton_1) + checkableLayout.addWidget(radiobutton_2) + checkableLayout.addWidget(radiobutton_3) + checkableLayout.addWidget(checkbox) + checkableLayout.addStretch(1) + + main_layout = QHBoxLayout(result) + main_layout.addLayout(button_layout) + main_layout.addLayout(checkableLayout) + main_layout.addStretch() + return result + + def create_text_toolbox(self): + result = QToolBox() + init_widget(result, "toolBox") + + # Create centered/italic HTML rich text + rich_text = "<html><head/><body><i>" + for line in POEM.split('\n'): + rich_text += "<center>" + line + "</center>" + rich_text += "</i></body></html>" + + text_edit = QTextEdit(rich_text) + init_widget(text_edit, "textEdit") + plain_textedit = QPlainTextEdit(POEM) + init_widget(plain_textedit, "plainTextEdit") + + self._systeminfo_textbrowser = QTextBrowser() + init_widget(self._systeminfo_textbrowser, "systemInfoTextBrowser") + + result.addItem(embed_into_hbox_layout(text_edit), "Text Edit") + result.addItem(embed_into_hbox_layout(plain_textedit), + "Plain Text Edit") + result.addItem(embed_into_hbox_layout(self._systeminfo_textbrowser), + "Text Browser") + return result + + def create_itemview_tabwidget(self): + result = QTabWidget() + init_widget(result, "bottomLeftTabWidget") + result.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored) + + tree_view = QTreeView() + init_widget(tree_view, "treeView") + filesystem_model = QFileSystemModel(tree_view) + filesystem_model.setRootPath(QDir.rootPath()) + tree_view.setModel(filesystem_model) + + table_widget = QTableWidget() + init_widget(table_widget, "tableWidget") + table_widget.setRowCount(10) + table_widget.setColumnCount(10) + + list_model = QStandardItemModel(0, 1, result) + + list_model.appendRow(QStandardItem(QIcon(DIR_OPEN_ICON), "Directory")) + list_model.appendRow(QStandardItem(QIcon(COMPUTER_ICON), "Computer")) + + list_view = QListView() + init_widget(list_view, "listView") + list_view.setModel(list_model) + + icon_mode_listview = QListView() + init_widget(icon_mode_listview, "iconModeListView") + + icon_mode_listview.setViewMode(QListView.IconMode) + icon_mode_listview.setModel(list_model) + + result.addTab(embed_into_hbox_layout(tree_view), "Tree View") + result.addTab(embed_into_hbox_layout(table_widget), "Table") + result.addTab(embed_into_hbox_layout(list_view), "List") + result.addTab(embed_into_hbox_layout(icon_mode_listview), + "Icon Mode List") + return result + + def create_simple_inputwidgets_groupbox(self): + result = QGroupBox("Simple Input Widgets") + init_widget(result, "bottomRightGroupBox") + result.setCheckable(True) + result.setChecked(True) + + lineedit = QLineEdit("s3cRe7") + init_widget(lineedit, "lineEdit") + lineedit.setClearButtonEnabled(True) + lineedit.setEchoMode(QLineEdit.Password) + + spin_box = QSpinBox() + init_widget(spin_box, "spinBox") + spin_box.setValue(50) + + date_timeedit = QDateTimeEdit() + init_widget(date_timeedit, "dateTimeEdit") + date_timeedit.setDateTime(QDateTime.currentDateTime()) + + slider = QSlider() + init_widget(slider, "slider") + slider.setOrientation(Qt.Horizontal) + slider.setValue(40) + + scrollbar = QScrollBar() + init_widget(scrollbar, "scrollBar") + scrollbar.setOrientation(Qt.Horizontal) + scrollbar.setValue(60) + + dial = QDial() + init_widget(dial, "dial") + dial.setValue(30) + dial.setNotchesVisible(True) + + layout = QGridLayout(result) + layout.addWidget(lineedit, 0, 0, 1, 2) + layout.addWidget(spin_box, 1, 0, 1, 2) + layout.addWidget(date_timeedit, 2, 0, 1, 2) + layout.addWidget(slider, 3, 0) + layout.addWidget(scrollbar, 4, 0) + layout.addWidget(dial, 3, 1, 2, 1) + layout.setRowStretch(5, 1) + return result + + def create_progress_bar(self): + result = QProgressBar() + init_widget(result, "progressBar") + result.setRange(0, 10000) + result.setValue(0) + + timer = QTimer(self) + timer.timeout.connect(self.advance_progressbar) + timer.start(1000) + return result + + def update_systeminfo(self): + """Display system information""" + system_info = SYSTEMINFO.format(sys.version, + QLibraryInfo.build(), + QSysInfo.prettyProductName(), + screen_info(self)) + self._systeminfo_textbrowser.setHtml(system_info) + + def help_on_current_widget(self): + """Display help on widget under mouse""" + w = QApplication.widgetAt(QCursor.pos(self.screen())) + while w: # Skip over internal widgets + name = w.objectName() + if name and not name.startswith("qt_"): + launch_help(w) + break + w = w.parentWidget() diff --git a/examples/widgets/systray/images/bad.png b/examples/widgets/systray/images/bad.png Binary files differnew file mode 100644 index 000000000..c8701a241 --- /dev/null +++ b/examples/widgets/systray/images/bad.png diff --git a/examples/widgets/systray/images/heart.png b/examples/widgets/systray/images/heart.png Binary files differnew file mode 100644 index 000000000..cee1302b7 --- /dev/null +++ b/examples/widgets/systray/images/heart.png diff --git a/examples/widgets/systray/images/trash.png b/examples/widgets/systray/images/trash.png Binary files differnew file mode 100644 index 000000000..4c24db926 --- /dev/null +++ b/examples/widgets/systray/images/trash.png diff --git a/examples/widgets/systray/main.py b/examples/widgets/systray/main.py new file mode 100644 index 000000000..4fad002a6 --- /dev/null +++ b/examples/widgets/systray/main.py @@ -0,0 +1,58 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +import sys + +from PySide2.QtWidgets import QApplication, QMessageBox, QSystemTrayIcon + +from window import Window + +if __name__ == "__main__": + app = QApplication() + + if not QSystemTrayIcon.isSystemTrayAvailable(): + QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.") + sys.exit(1) + + QApplication.setQuitOnLastWindowClosed(False) + + window = Window() + window.show() + sys.exit(app.exec_()) diff --git a/examples/widgets/systray/rc_systray.py b/examples/widgets/systray/rc_systray.py new file mode 100644 index 000000000..2d59adc74 --- /dev/null +++ b/examples/widgets/systray/rc_systray.py @@ -0,0 +1,2581 @@ +# Resource object code (Python 3) +# Created by: object code +# Created by: The Resource Compiler for Qt version 5.15.0 +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore + +qt_resource_data = b"\ +\x00\x00d\xb4\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x02\xe8\x00\x00\x02\xe8\x08\x06\x00\x00\x00*Z\x00\x90\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\ +\x9bx\x00\x00\x00\x07tIME\x07\xdc\x03\x09\x08\x1e\ +4hf\xd9|\x00\x00\x00\x06bKGD\x00\xff\x00\ +\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00d4IDATx\ +\xda\xec\x9d\x07\xb8U\xc5\xb9\xbf\xf7i\x1c\x0e\xe7\xd0\xcb\ +\x01Tz\x95\xa6 \xbd\x8b\x14E@\x10Q\x14\xa4\x05\ +\x14\x14\x14AAD\xaaT\xe9\xe7h\xd4\xab&\xc6$\ +\xb6\xc4DM\xa2&\x1a{\x895\xb1w\x05\xd9k\xa7\ +\xdc\x14M\x8c\xc66\xf7\x1b\xf6J\x82W\x84\xb5\xf6\xd9\ +k\xd6\xac\xb5\xdf\xf7y\xde\xe7\xb9\xf7\x7f\xff\xf7F\xcf\ +\x9e\xf9\xe6\xb7g\xcf|\x93H\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00@.Q(\xd6um\x22\xb6\x12;\x8a=\xc4\ +>\xe2q\xe2(\xf1x\xf7\xbf\xd6\xf6u\xff\xe7\xda\xa3\ +\xdc\xff\x9dz\xee\xff-\x00\x80\xaaRM\xac\xef\xd6\x96\ +\xee\xfb\xd5\x9b~\xfb\xd5\xa1\xd1\xe2\x08\xf7\xbf\xee\xed\xfe\ +\xcf\xdb\xbb\xff;\x8d\xf7\xabk\xf9\xfc9\x01\x00\xc0\x06\ +j\x8a\xdd\xc4\x93\xc4\x05\xe2*\xb1B\xfc\x81x\x8f\xf8\ +\x94\xf8\x8e\xf8\x81\xa8\xb2\xec?\xc5\xdf\x8bo\x8a\x0f\x8a\ +7\x89;\xc5\xe5\xe2,q\x8c\xbb\x90\xd6\xe3c\x02\xc8\ +)\x1a\x89\xbd\xc4\xb1\xe2\x1cq\x85[\x97n\x13\x1f\x16\ +\xdf\x12\xff(~\x1c@]\xfa\x8b[\x93~#\xfeB\ +\xfc\xbe[\x97V\x8a\xe7\xbau\xa9\x93X\x83\x8f\x09\x00\ +\x00\xaaB\xb3Dz\xf7h\xb6\xb8^\xbc\xd9]|\xfe\ +\x14\xc0\xe2\x16\x94\x1f\x8a/\x88w\x8a\xbb\xc4\x0b\xc4\x13\ +\xc4\xe6|\xbc\x00\x91C\xefT\xb7\x16\xc7\x89\x17\x8aW\ +\x88?\x17_\x16?\x8aP]J\x89\x8f\xbb\x1b\x1ak\ +\xc5\x99\xe2\xb1\x89\xf4/\x8c\x00\x00\x00\xfb\xa8\x9eH\xef\ +8\xebEB\xef\xf8<\x90H\xef\x06\xa9\x98\xfb\x81\xbb\ +H^\x93H\xff\x0a\xa0\x7f\xc6\xae\xc3p\x00\xb0\x82\x86\ +\x89\xf4\xd1\xb7E\xe2\xf5\x89\xf4\xafr\xff\xc8\x81\xba\xa4\ +w\xf8\x7f%^.N\x15\xbb\x8aE\x0c\x07\x00\x80x\ +\x93\x97H\xff\xcc\xaaw\xc5\xbf#\xbe$~\x96\x03\x8b\ +\x9eW\xbf\x14_\x17otC\xbb>\x0b_\xca\xb0\x01\ +\x08\x94Z\xe2 q\xb1x\x8b\xf8.\xb5\xe8+\xfeK\ +|\xde\xddL\x98&\xb6e\xc8\x00\x00D\x1b}\x09J\ +\x9f}\xdc(>\x9a#;PA\xf8\xb6x\xb5x\xa6\ +x\x04\xc3\x0a\xa0J\xb4H\xa4\xcf\x88\x7f\xcf\x9d[\xd4\ +\x18\xff\xfe\xdd\xad\xe9\x1b\xdd\x1a\xcf\xaf\x7f\x00\x00\x16\xa3\ +;\x13\xe8\xb3\x8c\x9b\xc5\xa7\x13\xec\x8e\x07\xe1\xe7\xe2\xb3\ +\x89\xf4O\xd0\xfaXLu\x86\x1d\xc0A)sC\xa4\ +\xbe\xb0\xa9\x7f\xb5\xfb\x92:\x92u?\x11\x1fK\xa4\xcf\ +\xb4\xeb_\xfe\x0a\x18v\x00\x00\xe1\xa2\xcf\x8f/I\xa4\ +\xcf-\x06\xd1\x9d\x00\x0f\x1d\xd8\x9fqw\xb2t`\xa7\ +\x15$\xb0Q\x90\x9e\x0b\x1b\xdd\xb9\xf1\x05u\xc2\xb8\x1f\ +\xb9k\xc2y\x09.\xc5\x03\x00\x18A\x9f#\xd7\xad\xc4\ +6\x89/\xb2\x10Y\xe7\x1eq\x878 A\x7fd\xc8\ +\x1d\x0a\xddP~U\x22\xdd\x06\x95Z`\x8f_\xb8_\ +\x94V\x8b]\x18\xaa\x00\x00\xd9\xe5\x98D\xfa\xe8\x0a\x17\ +\xa8\xa2\xa3#V\x8aC\x13\xfc\xe4\x0c\xf1C\xef\x94\xeb\ +\x07\xc6\xae\x15\xff\x97\xf9\x1e\x19_u\xc3z'\x860\ +\x00@f\xe8\x17\xee\xf4\xcf\xc4\x5c\xa4\x8aG\xfb4\x1d\ +\xd6\xf5\xf9\xd0<\x866D\x14\xfd\xab\xd0\xb0D\xba\xf5\ +\xe1\xdf\x98\xd7\x91W\xf7\x90\xd7\x8f)udh\x03\x00\ +\x1c\x9c\x96\x89\xf4E\x9f7Y<b\xab~\xd1pM\ +\x22\xfdl8@\x148J\xdc\x22\xeee\xfe\xc6V}\ +d\xf2\xe2\x04\x0f&\x01\x00\xfc\x07\xfd\x10\xc5\xc9\xe2=\ +\x09.T\xe5\x9a\x0f\x89\x93\xc5b\xa6\x01X\x86~\x03\ +@?`\xf64\xf34\xa7\xd4\xdd\xbfnO\xa4\x8f/\ +q\x8f\x06\x00r\x12\xfdl\xf5\x86D\xfa\xe9g\x16\x86\ +\xdc\xf6O\x89t\xeb\xc6vL\x0b\x08\x99n\xe2\x15\x09\ +\x8e\xb0`\x22\xf1\x9ex\xa9x\x18\xd3\x02\x00\xe2\x8e>\ +\x7f<R\xfce\x82\xddr<\xf0k\xa6\xf7\x8b'\xb2\ +{\x05\x06\xd1]XN\x13\x9fd\x0eb\xe2\xc0\xbb\xea\ +?\x15\x072U\x00 n\xe8\x07m\xbe\x95H?\xd4\ +A\xc1G/\xea{\x08\x0b\xc4\x9aL\x1f\x08\x88\xda\xe2\ +bq7\xf3\x0d=\xaa\x8f<\xe9cyEL\x1f\x00\ +\x882\x8d\xc4U\xe2\x1f(\xec\x98\xa1\x1f$\xd2\xbd\xd5\ +[3\x9d K\xe8\xcb\xe8\xdb\xc5\x0f\x99_\x98\xa1\xfa\ +\xcd\x87\x0b\xc5:L'\x00\x88\x12\xba\xc7\xec\xff$x\ +\xdd\x13\xb3\xfb3\xf3\xf7\x12\x9cS\x87\xcc\xd1\xddX\xf4\ +\x05\xc0/\x99O\x98%\xf5\x97\xbc\x9db+\xa6\x17\x00\ +\xd8\x1e\xccoc\x01\xc4\x00\xfd\x5c\xfc~\x82\xde\xc5\xe0\ +\x9d\x1e\xe2\x1d\xd4%\x0cx\x03A\xf7\xc7o\xc1t\x03\ +\x00\x9bh\xeb\x86&.~\xa2\xc9'\xbco\x22\xa8\xc3\ +A\xe8%\xfe\x8c\xb9\x82\x06\xfd\x97\xf8m\xf1p\xa6\x1f\ +\x00\x84\x89\xde-\xb8\xce\xdd=\xa08cX;\xea\xdf\ +\x11\x9b1\x1d\xc1E\x7fi\xe3(\x0b\x86\xa9>\xde\xa9\ +\xef\xce\x943\x1d\x01\xc0$\xba\xe8\x5c\xe1\xee\x16P\x8c\ +\xd1\x06?I\xa4/\xfe5dz\xe6,\xfaK\xda\xf5\ +\xee\x976\xe6\x04\xda\xe0?\xc4\x8d\x89t\xc7 \x00\x80\ +\xc0\xa8\x96H\xb7%\xe3\x11\x0f\xb4\xf9\xd2\xd6j\xb1\x8c\ +\xe9\x9a3\xd4w\xbf\x9c}\xc2\xf8GK\xfd\xbd8[\ +,`\xba\x02@\xb6\x19\x9fH\xf7\xa6\xa6\xd8b\x14\xdc\ ++NI\xa4\x1f\xc7\x82x\xa2\x1f\x18:G\xfc3\xe3\ +\x1d#\xe2\xef\xc4c\x99\xba\x00\x90\x0dtk\xb2_S\ +X1\xa2>&\x1e\xc34\x8e\x1dC\xc5\x17\x18\xdf\x18\ +Q\xf5\xcb\xa4m\x99\xc6\x00\x90\x09\xfa\x9c\xb9\xeeeN\ +g\x16\x8cC\xc7\x17}\x99\xb91\xd3:\xf2\xe8~\xd3\ +\xb71\xa61\x06\xea;\x5c[\x13<v\x04\x00\x1e\xd1\ +G\x02\xe6\x88\x7f\xa5\x80\x1e\xda\xeab;\xb1\xaf8F\ +\x9c.^ ^&^)\xde*\xde\xe3\xfa+\xf1\x09\ +\xd7\xe7\xc4W\x0f\xe2\xf3\xe2\xc3\xe2\xcf\xc5[\xc4k\xc4\ +m\xe2\x12q\x968\xce\xfd\xcf\xd4\xff\xd9\xf5\xf8\x1c\xbc\ +\xfa\x17qV\x82c/QD\x1fg\xd1/7~\xc4\ +8>\xb82\xb8U\x03\xb1\xbd8@\x9c \xce\x16\x97\ +\x89\xdb\xc5k\xdd\x9ar\xb7\xf8\xa8[k\x0eV\x8b\x9e\ +\xd9\xafn\xdd\xbb_=\xbbI\xbcB\x5c+.\x14\xcf\ +\x14O\x10\xfb\x88\xad\xc5b>\x0b\xaf:\xe2D\xa68\ +\x00\x1c\x0c\xa9\xe9\x89\x87(\x98_\xb5\x898D\x9c!\ +\xaep\xc3\xf2/\xc4\x17D\xc7\x12\xdf\x16\xef\x17\xaf\x17\ +W\xba_\x14\x06\x89\x87\xf1\xf9\x1d\xc8\x07\x12\xfc\xbc\x1c\ +%\xba\x8b\xcf1n\xffk\xbe\xd8L<V\x9c)\xae\ +\x11o\x10\xa5x\xabw-\xaaK:\xfc\xdf%~[\ +\xbcD\x9c&\x0e\x14\x1b\xf2\x19\x1eH\xfd\x98\x16\xfd\xd3\ +\x01\xe0+\x14\x89\xcb\x13\xe9\xde\xad9[ k\x89=\ +\xc5\xa9\xe2z\xf1vw\x07\xc9\x89\xb8o\xb8_(v\ +\x8as\xc5\xfe\xee\xbfk\x8e/\x86z\xac/\x13\x8b\x99\ +\xfe\xd6R*^\x9e\xc8\xf1w\x16\xf4/d\x83\xc5s\ +\xdd_\xe5~\xe9~!\x8fz]z\xd1\xfd\x85Q\x7f\ +\xb98]<Z,\xa5.}\x90H_|\xceg\xfa\ +\x03@\x1f\xf1\xc5\x5c,\x86\xfag\xd8\xc9\xe2\x0e\xf1\xf1\ +\x18,x~L\xba\xff\xceW\x89g\x89\xdd\xc4\x82\xdc\ +\x5c\x10_Np\x89\xd4F$\x93&\xde\xc9\xb5\xf1X\ +\xe4n\x12\xcc\x17\xaf\x13\x9f\xca\xc1\xba\xa4\x7f\x05\x90o\ +ej\xa2xDn_n\xefD\x19\x00\xc8MJ\xc4\ +\x9d\x89\x1c\xb9\x04\xaa\xc3\xe7Q\xeeY\xcck-;\x9e\ +b\x8b\xaf\x8b\xdf\x13\xe7\x89\xdd\xc5\xc2\xdcY\x0c\xf5\x0e\ +\xed*\xf7\x97$\x08\xbf.m\xcb\x95\xbaTM\xec\xed\ +\x9e\xe1\xbe%&;\xe3\xd9\xf6Y\xf7\x97\x83\xe9bG\ +\xf7\x8c}\x8e\xd4\xa5\x7fQ\x97\x00r\x8f\xfe\xe2\xbbq\ +/p\x87\xbb\x17*Y\xf82\xf3\x1d\xf7ow\x8e\xd8\ +57\x16\xc6\x97\xc4\x1e\x94\x87\xd0\x18\x12\xf7\xba\x94\xef\ +\xee\x90_\xe2^\xb4|\x9f:\xe3\xdb7\xdd\xf3\xf6S\ +\xdc\xfbA\x89\xdc\xa8K])\x0f\x00\xf1F\x9fk\xd3\ +/\x81\xc6\xf2\xc5=\xbd\xf8\x1d\xe3v:\xb9\xd7\xfd\xb9\ +\x94\x05-{\xea.\x0e\x17\xbb\xbfD\xc48\xac\xeb\xb3\ +\xe9\x92\x9fx\xf1\xcf \xfao\xbd2\x11\xd3\xb3\xe6\x05\ +ng\x93\x95n\xf7&jI\xf6\xd4_p\xee\x14\xcf\ +\x17\xbb\xc4;\xa4\xff=\x91\xee@\x05\x001\xe40\xf1\ +Wq,^G\xb9\x8b\xdf\xb3,XF\x7fv^\xe7\ +\xb6q\x8b\xe9Q\x98\x07\x13tT0\xc1\x11\xe2\xc3q\ +\x1b?\xfa\xe8\xcapq\xab{\x19\x92\x9aa\xc6\xc7\xdd\ +\x0d\x9a\x0e\xf1\x0d\xea\xfa\x0d\x80z\x94\x0d\x80\xf80A\ +\xfc\xdf8\x15\xaa\x0en!~\x9cE)t\x7f\xe7\xf6\ +B>:~\x8b\xa1\x9e3\xe3(\x1f\x811^\xfcs\ +\x9c~\xc1\xeb\xeb^p|\x95\xba\x10\xba\xbf\x16\xcf\x13\ +[\xc4\xaf.\xbd\x9fH\xbf\xa4\x0b\x00\x11\xa6\x9axe\ +\x5c\x0aSC\xf7<\xf4\x83,>\xd6\xfa\x98\xb8(^\ +gC\xbf\x14+\x13\x5c\xd4\xca&\xa5q\xaaK-\xdd\ +3\xe5O3\xff\xad\xf5\x1e\xb7_|\xedx\xbd\x8e\xbc\ +:A;F\x80H\xa2\x7f\x9e\x7f\x22\x0e\xbbR\x83\xdc\ +\xc7\x81v\xb3\xd0D\xeal\xa8\xbe\xc8u\x5c|\xda7\ +\xea\xc7\x8d\xca)+U\xa6\x83\xf8j\xd4\xc7\x83n\x87\ +8\xd6\xed\xe3\xcd]\x97h]|\xd7\xefA\xf4\x8aO\ +P\xff\x99X\x97\xb2\x02\x10\x1d\x86\x88\x7f\x88r\xe1)\ +w{\x01?\xc1\xa2\x12y\xf5\xce\xe2\x05\xf1\xd8U\xdf\ ++\xf6\xa3\xbcd\x8c>\xd2\xf2a\xd4w\xcb\x97\xd3\xa6\ +5\x16>\xe8\xb6\xdd\xad\x1b\xfd\xba\xf4\x96\xd8\x8d\xf2\x02\ +`7\xfa\xe7\xae\x8d\x89\xf4\xcf\xf2\x91,6\xc7\xb8;\ +\xaf{\xa3\xfc\xd8Fa\xa1J\xd5\xae\xadRM\x9b*\ +\xa7m[\xe5t\xeb\xa6\x92\xfd\xfa)g\xc4\x08\xe5\x8c\ +\x1b\x97v\xd2$\xe5L\x9e\xac\x9c)S\x943k\xd6\ +\xd7L\x9dqF\xfa\x7f\xae=\xe9$\xe5\x8c\x1c\xa9\x9c\ +\xc1\x83\x95\xd3\xab\x97r\xbavM\xff\xdfm\xdcX9\ +\xc5\xc5\x91\xf9\xbb\xecu?\xdb\x81\xd1^\x0c?O\xa4\ +{\x13\xf3\xd3\xb2w\xf4\xf1\xa0\xab\xa3\xfa\x99\xe7\xb9\x17\ +>\x7fJ\xa8\x8d\xa5\xbb\xdd]\xf5\x88_,\xd5\x9d\xd9\ +\xce\xa3\xd4\x00\xd8IM\xf1\xd6\xa8\x16\x18}\x8c\xe5\xe6\ +\x08\x05p\xa7\xbc\x5c9G\x1e\xa9\x9cA\x83\x943~\ +\xbcrf\xcfV\xce\xd2\xa5\xca\xd9\xb2E9W\x5ca\ +\xd4\xe4\xd6\xad\xcaY\xbe\x5c9\xf3\xe7+g\xeaT\xe5\ +\x8c\x1a\xa5\x9c\x1e=\x94\xd3\xac\x99rJJ\xac\xfc\x1b\ +\xea\xb0s\xbc{\x84)\xa2c\xf6\x87b\x0d\xca\xce!\ +\xd1\x1d'\xee\x8e\xe2g\xac\x8f\xb1\x9c,\xfe\x92\x10\x9b\ +\x13\xea\x0d\x84\xeb\xdcM\xa2\x08\x07\xf5+\x12\xe9\xbbg\ +\x00`\x09m\xc4W\xa2VLt{>\xfd\x9c\xf3}\ +6\x17\xee:u\x94\xd3\xa9\xd3\xbe\xdd\xef\xd4\xcc\x99\xfb\ +\x82p\xaa\xa2\xc2x\x08\xaf\x92\x1b7*\xe7\xfc\xf3\xd3\ +\xbb\xf6\xfd\xfb+\xa7E\x0b\x95\xaaV\xcd\x8a\xbf\xef\xc3\ +n\x08\x8a\xe89\xf5g\x13\xb4b<\x18\xfa\xbc\xf9\x9b\ +Q\xfb\x5c\xab\xb9\xafVr\xe93w\xd5\xbd\xd5GE\ +\xf7\xbd\x87\xc7\xc5\xc6\x94\x1f\x80\xf0\xd1\xaf\x82\xfe)J\ +\x05D\xef\x9a\x8e\x17\x1f\xb5\xad0\x97\x95)\xa7sg\ +\xe5\x8c\x19\xa3\x9c\x05\x0b\x94\xb3ys\xb4\x82\xb8\x1f+\ ++\x95\xb3b\xc5\xbe\x1d\xf7}\xc7o\xf4q\x99\xbc\xbc\ +P\xbb\xbfL\x8afOu\xf9\xc7O\xf4\xa2\x0c}\x8d\ +\x91\xe2_\xa3\xf4Y\x16\xbb\x9d>xL\x08\xff\xed/\ +\xdd\xe3M\x11\x0c\xe9\xef\x89\x9d)C\x00\xe1qZ\x22\ +\xfd\xf2ad\xcer\x9e\xe0\xf6\xa7\xb5\xa1\xf8\xa6\x9a4\ +Q\xa9\x81\x03URBjj\xe5\xca\xf8\x86q\xaf\xea\ +/$g\x9f\xad\x9ca\xc3\x94s\xc4\x11\xa1\x04v\xdd\ +\xd7\xfe\xa4\xe8\x1d}\xd1s\xf0t\xca\xd1\x7f\xd0ga\ +?\x8f\xd2Q\x96\xa9\xe2\xf3\x04R\xfc\x06\x7f\xe6\x1e\xc3\ +\x8cXH\xff\x9b8\x9cr\x04`\x1e\xfd\x1cyd.\ +\x83\xeav{\xf7\x86]h\xf5\xb1\x8e\xae]UJ_\ +\xbc\x5c\xbb\x96@\xee%\xb0\x7f\xeb[\xca\x91/1N\ +\xc3\x86F?+}\xeciX\xf4\xfa\xa5_\x9a\xe35\ +I_\x9c\xad\x88\xd2\x86\xc18\xf7\xd7\x1bB(z\xf1\ +v\xb1w\xb4\xea\xd2\xa7\xe2l\xe2\x12\x80\x19tG\x84\ +\xeb\xa3R \x8et{\x05\x87VT\x1b4H\xef\x08\ +\xcf\x9f\xafR;w\x12\xba\xab\xa2\xbe\x88:f\x8cJ\ +\xea\xcb\xa7\x86v\xd7\x7f\x12\xbd\x17J\xf5\xa3F\x059\ +X\x97\x8a\xc5\x9b\xa3\xf29\x0d\xe0\xf2'V\xc1\xeb\xa2\ +\xf7B\xa9\xee\xee\x96G|\x02\x08\x8e:\xe2\xfdQ(\ +\x08\xfa\xd5\xcf\xcb\xdd\x07kB\xb9\xd8y\xec\xb1\xca\xb9\ +\xf0BBuP^v\x99rN9E9-[\x06\ +\x1e\xd6\xf5C0\x15\xd1\xea\xa3~\xbbX\x92cu\xe9\ +\x81(|6\xba\x8f\xf9w\x09\x98\x98\xa5\xf6\x8c\x97\x8a\ +\xb5\xa2S\x97n\xcd\xb1\xba\x04`\x8c\xfa\x89t\xd7\x08\ +\xeb; \x9c#\xben\xba\xf5\xa1\xbe\xe0\xa9[\x1e.\ +\x5c\x98\xbe\x00I\x886fj\xf5j\xe5\x8c\x1e\xad\x9c\ +F\x8d\x02\xfd\x8c\xdf\x16\x17\x89%\xd1X\x0c\x1fM\xa4\ +[\x0c\xc6\x1d\xdd\xc5\xe6\x05\xdb?\x0f\x1d\xa2V\xf1\x1a\ +1\x06\xe0\x8b\xe2\x99\xd1\xe9D\xa5\xebRm\xe2\x14@\ +\xf6h\x22\xbeh\xfb\xe4\x1f->i\xb28\xe6\xe7\xa7\ +[ \xce\x99\xa3\x9c]\xbb\x08\xcb6\x84\xf5\x0b/\xdc\ +w\xf16\xc8\xfe\xebOG\xa7\xb3\xc2+\xee\xdc\x8d+\ +\xed\xc5\xf7m\xff\x1c\xc6\xf3\xf2'\x1a\xf0~\xf7\xe8T\ +\x04\xea\xd23b\x03b\x15@\xd5i+\xee\xb6\xfdg\ +\xe3\x1f\x9b\xec\xbe\xa2_\xe8<\xe5\x14\x95\xd2\xfd\xbd\x09\ +\xc5v\xaa\xcf\xfb\xebWQ\xbbtI\x7f\x91\x0a`\x1c\ +\xdc&\xb6\x8aF\xbb\xb3\xd61\xacK=\xc5\xbf\xd8\xfc\ +\xb7o\xcf\xeb\x9f\x18\x82\xfa\xb5\xe4\xc6\xf6\xd7\xa5\xd7\xc4\ +#\x88W\x00U\xdb\xa1\xdac\xeb$\xd7]\x10\xce\x10\ +_3Q\xf8\xf49\xe7\xce\x9dU\xea\x9cs8\xc2\x12\ +\xb5]\xf5K/U\xa9\xc1\x83\xd3]t\xb2<.\xde\ +\x10g\xd9\xdf\x96\xf1\x1d\xb1e\x8c\xea\xd2Q\xe2\x1fm\ +\xfd{\xeb\xb6\x89\xe7\x89\xef\x10\x161$\x7f'\x8e\xb5\ +?\xa4\xbfAH\x07\xc8\x8cn\xe2\x1fl\x9d\xdc-\xdc\ +\x1dL#\xad\x11\x87\x0eU\xce\x9a5\x84\xdd\x88\x9b\xdc\ +\xba5\xfd\xcbG\xbdzY\x1f'\xfa\x17\x9c\xe6v/\ +\x86\xfa\x8bv;v\xce\x83\xef\x1aEw\x16\xb4\xc5\xef\ +\x88\xe5\xfc\xc2\x07\x10+\xfa\xd8\xba\x08\xea\x9d\xca\xb3\xdc\ +\x0b{\x81\x16\xb7\x1a5Tj\xe4H\x95\xda\xb0\x81p\ +\x1b\xb7\x1d\xf5\x9d;U\xea\x8c3T2\xcb\x97J\xdf\ +\x12g\xd8\xfd<\xb7~u4\xca\xaf\xfb\x0d\x10?\xb0\ +u\xd7\xfc\x02.\x81\xa2\x85\xea_\x98O\xb5;\xa4'\ +\xc5\x0e\xc4.\x80C\xd3[\xfc\xd0\xc6\x89\xdc\xd8DO\ +\xf3\x9a5\x953a\x82r\xb6m#\xcc\xc6\xdd\x8a\x0a\ +\x95\x9c>]9M\x9adu\x0c\xfd\xc8\xee\xdd\xf4?\ +\x89]\x22X\x97\x06\x89\x1f\xb1k\x8e\x98\x99\xd7\x88u\ +\xec\xadK\xef\xc7\xec\x18\x1e@ \xc7Z\xac\xdc9\xd7\ +\x1dZ^\x09\xb2\x80\xd5\xae\xad\x1c\xfd\xc2'\x8f\x09\xe5\ +\xa6\xfa!)\xddS=K\xe3\xe9M\xbbw\xad~\x9f\ +H\xdf/a\xd3\xa0\x8aw`\xcef\xd7\x1c#\xe4\xb3\ +b\x7f\xbb\xef\xca\x1cN\x0c\x03\xf8:G\x8b\x7f\xb5m\ +\xd2\xd6\x16\xaf\x0e\xb2h\xe9v|'\x9e\x98>\x9fL\ +P\xcdm++UJw~i\xd80\xabg@\xeb\ +\xda\xb9\x18\xea\xfb%GF\xe4X\xcb?l\xfc5\xef\ +G\x04>\x8c\xa0\xfa\xe1\xb5\xcd\xf6\xbe\xe7\xa0;\xc65\ +'\x8e\x01\xfc\x97\x16\x09\x0b\xfb\x09\xeb'\xd6\x1f\x0b\xaa\ +P\x15\x15)g\xe4H\xe5l\xd9B0\xc5\xaf\xaa{\ +\xdaO\x9a\x94>\xee\x94\x85\xb1\xa6{\xf3w\xb7\xf7\x82\ +V3\x8b\xebRg\xf7H\x8eU\x7f\xb7\xc1\xe2o\x09\ +z\x18q\xef\x16[\xdbY\x97\xf4\xc3c\xf5\x89e\x00\ +\x89DS\xf1-\xdb&\xe9\xb7\x82\xfa\xe9X\xb7K\xec\ +\xd1C9k\xd7\x12D\xf1\xd0]_\x8e?>\xfde\ +.\x0b\xcfr\xcf\xb0\xb7\x1f\xb1\x8d\x8f\x86\xb4J\xa4/\ +\xb5ZuA}\xb1\xbb\x03I\xc0\xc38\xa8\x9b-L\ +\xb0\xb3.=\x9d\xe0\xc5Q\xc8q\xf4\xc2\xfc\xb2M\x13\ +\xb3\x86xeP\x05\xa9M\x1b\xe5,]J\xf8D\x7f\ +]_\xd6\xafWN\xef\xde\xe9/wU\x1c\x83;\xc5\ +b\xfb\x16\xc3\xdf\x88\xa5\x16\xd5\xa5\x86\x89t\x8fdk\ +\xfeF\xb5\xc4\xef\x11\xe80\xa6^\xe6v\x22\xb2\xac.\ +=jY]\x020F\x89\xf8\x84M\x13\xb2\xa5\xfb\x5c\ +q\x10\x17@\x93S\xa7\xf2\xc0\x10V\xcdy\xf3\xb2r\ +>\xfd^\xf1p\xfb\x16\xc3_\x88E\x16\xd4\xa52\xf1\ +)\x9b\xfe6\x1d\xc4\xc7\x09q\x18s\xef\xb0\xb3g\xfa\ +\x9db\x01q\x0dr\x89|\xf1v\x9b&\xe2\x88 ^\ +\x04\xd5;\x9e\x83\x06)\x87\x0b\xa0\x98\xc5\x1e\xea\xce\xe8\ +\xd1*YXX\xa5\xb1\xf9\x92x\xac}\x8b\xe1\x0db\ +^\x88uI\x7fA\xb8\xc7\xa6\xbf\xc9x\xb7#\x0f\x01\ +\x0esA}\xb7\xa2\x8f}u\xa9\x92\xc8\x06\xb9\xc4v\ +\x9b&\xe0\x1cqo\xb6\x8bM\xf3\xe6\xcaY\xb6\x8cP\ +\x89\xc1\xb8f\x8dJv\xe8P\xa51\xfa\xbe8\xcb\xbe\ +\xc5pc\x88u\xe9\x06[\xfe\x0e\xba\x85\xe2E\x9c7\ +\xc7\x1c\xf4=\xf1d\xfb\xea\xd2\x22b\x1b\xe4\x02\x17\xda\ +2\xe9\xf4\x99\xb7\xed\xd9.0\xc5\xc5\xe9\xe7\xdc+*\ +\x08\x91\x18\xbc\xba-cYY\x95\xc6\xecv\xfb\xce\x7f\ +\x9e\x13B]Ze\xcb\xbf\x7fM\xf1\xfb\x045\xccq\ +\xd7\xb8\x17\xa3-\x99\x97_\x8aS\x89o\x10g\xc6\x89\ +\x9f\xdb0\xe1\xca\xc4\x1b\xb3\x5cP\xf4C3\xa9K/\ +%4\xa2Y/\xbb\xac\xca\xbb\xe9?\x10K\xedY\x0c\ +\xff%\x0e1X\x97&\x88_\xd8\xf0\xef^_\xbc\x8b\ +p\x86\xb8\xcf]vm\x1e\xfcS\xecG\x8c\x838\xd2\ +_\xfc\xd8\x86\x89v\x84\xf8`6\x0b\x89>\x0f|\xca\ +)\x5c\x02\xc5p\x9d6-\xfd\x0bN\x86\xe3\xf8\x01\xb1\ +\xa9=\x8b\xe1\x07\x89t\x1f\xf2\xa0\xe9kK]\xd2=\ +\xa1\x7fC(C\xfc\x8a?\x13\x1b\xdaS\x97\xfe&v\ +!\xceA\x9c\xd0\xcf\xe7\xa6l\x98`\x9d\xc4\xe7\xb2Y\ +@\x1a5R\xceE\x17\x11\x0e\xd1\x9a\xb3\xe9N\xabV\ +\x19\x8f\xe7'\xdcnF\x96,\x86\xaf\x8au\x02\xacK\ +\xfa\x0d\x86\xbd6\xfc\xbbv\x14\x9f'\x8c!\x1e\xd0G\ +\xc4\x16\xf6\xd4\xa5\xd7\x03\xaeK\x00\xc6(NX\xd2N\ +\xf1\x98lwj\xe9\xde]9\x97_N(\xc4\xc0^\ +\x14Mm\xd8\xa0\x9c\xe5\xcbUr\xe1B\xe5\xcc\x99\xa3\ +\x9c3\xceP\xa9\xf1\xe3\x953n\xdc\xben.\xa9\x11\ +#\x943|\xb8r\x06\x0c\xf8\xaf\x03\x07\xaaT\xf5\xea\ +\x19\x8f\xeb\x17\xedzy\xf4\xdeD0m\xcet\x9b\xd7\ +gl\xf8w\xec\x1bD\x07)\xc4\x98\xa9\xbf\xc0\xb6\xb3\ +\xa7.\xdd\x95Hw\xa3\x03\x884\xdf\xb6aB\xf5\xcf\ +f\xbb2\xfd\xb2\xe3\x94)\x04H\xac\x9a[\xb6\xec{\ +\xb8*5{\xb6rt\xe8\x96`\xed\x1cy\xa4J6\ +jT\xa5\x80\x9d\x0d\xdf\xb0\xab\xdd\xd9\xfa\x00\xea\x92\x15\ +\x1d[F\x89\xef\x12\xbe\x10=\xb7\x87\xedlO]Z\ +A\xbc\x83(s\xb6\x0d\x13\xe9\x04\xf7\xa9\xf3\xac\x14\x89\ +\x06\x0d\x94s\xf1\xc5\x84K\xf4\xd7\xbb\x5c\xbf \xab\x1f\ +\xab\x1a6L9\xed\xdbW\xb9\xf3\x8a\xa9vg#\xed\ +Y\x0c'e\xb1.\x9do\xc3\xbf\xd3\xa9n\xabK\x82\ +\x17\xa2w\xdf\x12\x07\xd8\xd3\xd9\xe5db\x1eD\x11\x99\ +C\x89O\xc3\x9eD\xa7ds\x11\xec\xd4\x89#-x\ +\xf00\xae\xdbk\xea0~\xea\xa9\xca\xe9\xd5K9M\ +\x9a\xa8d~~d\x17\xc3\xdd\xee\x17\x5c\x0b\x16\xc3\xbf\ +\x8b\x9d\xb2P\x97\x06\x89\x9f\x85\xfd\xef3\x83\x1e\xe7\x88\ +\x19\xfb\xb68\xc4\x8e\xba\xf4\xa1\xd8\x91\xb8\x07Q\xa2\xbe\ +\xf8^\xd8\x93G\xbf\xc2\xb7'[/\x82\x8e\x1eM\x97\ +\x16\xfc\xba\xfa\x0b\xdb\xd9g+g\xe4H\xe5\xb4m[\ +\xa5.*6\x87\xf4\xe3\xedX\x0c_\x14K\xabP\x97\ +\x1a\x89\xef\x87\xfd\xef1%\x88\x87\xd1\x10s\xccw\xec\ +y\x0d\xf9y\xb1\x06\xb1\x0f\xa2\x80\xbe\xd0uo\xd8\x93\ +fL\xb6v\xcek\xd4P\xce\xbcy\x04QL\xab\xbf\ +\xa4\xe9\x1d\xf2\xb1c\x95\xd3\xba\xb5r\x22\xbc;\xee7\ +\xa4\x8f\xb2c1\xfca\x86uI_\xe8\xba/\xec\x7f\ +\xfe\xa9\xec\x9c#f\xb5.\x1dgG]\xfa\x1e\xd1\x0f\ +\xa2\xc0\xea\xb0'\xcb\xf0l\x9d9\xaf_\x9f\x87\x87P\ +9\xdb\xb6)\xe7[\xdfRN\xdf\xbe*U\xbbvN\ +/\x86\x96\xecX\xcd\xcc\xa0.-\x0f\xfb\x9f{\x12;\ +\xe7\x88\x81\xec\xa4\xf7\xb7\xa3.\xcd&\xfe\x81\xcd\xf4\x0b\ +\xfb|\xe7`\xf7r[\x95'~\x9b6\xca\xd9\xbc\x99\ +p\x9a\xa3&\xb7nM?\xfc\xa3_\xe8\xcc\x91]r\ +\xaf\x8b\xa1\x05\x17\xb4\xfe!\xb6\xf7Q\x97\x06\x86]\x97\ +\xc6r!\x141\xd0\xaeS\xdd\xed\xa8K\xed\x88\x81`\ +#\xb5\xc4\xb7\xc3\x9c }\xdc\xcb#U\x9e\xf0={\ +\xa6;o\x10Ts\xcb\xed\xdb\xd3\xa1\xbcK\x97t+\ +M\x16\xbeo\xec\xa2\xd0+\xfc\xc5\xf0\xb9D\xfa\x8d\x05\ +/\xf7a\xf6\x84\xf9\xcf:\x22\x9b]\xa4\x10\xf1\x80\xbe\ +*\x1e\x19~]zZ,\x22\x0e\x82m|7\xcc\x89\ +\xd1\xc3\xfd\x16]\xe5\x89>t(\x97As\xad\xf3\xca\ +\x8a\x15\xfb\xda\x1f&#\xd0\xfa\xd0\xa6\xc5\xb0C\xf8\x8b\ +\xe1\xb6C\xd4\xa4<\xf1\xce0\xff\x19{\xb9\xbf:0\ +f\x10\x83\xf7\x05\xb1u\xf8ui\x1dq\x10l\xe2\x94\ +0'D[70T\xb9S\xcb\x84\x09\x04\xd6\x5c\x09\ +\xe5;v(\xe7\xcc3UJ\x1feba\xcb\xc8\xe7\ +\xc4\xc3\xc2\xefC<\xea uiv\x98u\xa9}6\ +\xea\x12\x22\xfa\xf2\x19\xb1<\xdc\xba\xf4\xb9{\xac\x0e \ +tZ\x88\x7f\x0bk24I\xa4\x9f\x00\xaej8O\ +\x9dv\x1a\xc15\x17\x82\xb9\xbe\xf4;h\x90rJJ\ +X\xcc\xb2\xe0\xe3b\xa3p\x17\xc3?\x8a\xe5\x07\xa8K\ +m\xc4\x8f\xc2\xfa\xe7j)\xbe\xc8\xf8@\x0c\xc5\x07\xc5\ +Z\xe1\xd6\xa5\xbd\xee\xf1:\x80\xd0\xd0\xad\xcb\xee\x0fk\ +\x12T\x17\xef\xaa\xead.(P\xce\xcc\x99\x84\xd78\ +\xab\x1f\x0f\x9a5+\xdd\x16\x91\xc5+\xeb\xea9Xl\ +W\xebE}\xb4%\xb4\x96\x8ae\xe2\xfd\x8c\x0b\xc4P\ +\xbdA,\x08\xb7.\xddHD\x840Y\x10\xd6\xe0\x97\ +o\x06\xea\xea\xaaNb}\x11p\xee\x5c\x02l\x9c/\ +}\x9er\x8aJ6h\xc0\x82\x15\xb0W\x8ay\xe1.\ +\x86\xa7\xecW\x97\xe6\x86\xf5\xcf\xa1\x03\xc1\xf7\x18\x0f\x88\ +V\xb8.\xfc\xf3\xe8'\x12\x13!\x0c\x9a%\xd2\xcfo\ +\x872\xf0/\xa9\xe2\xc4M\x16\x16*\xe7\xac\xb3\x08\xb1\ +q\x0d\xe6'\x9d\xa4\x9cZ\xb5X\xa4\x0c\xba0\xdc\x85\ +\xf0Obc\xb1e\x98u\xe92\xc6\x01\xa2U~+\ +\xdc\xba\xa4;H\xd5\x22.\x82i~\x1e\xd6\xa0\x9f\x9c\ +\x8d\x9d\xf3\xf9\xf3\x09\xb2q\xbc\xf89n\x9crJK\ +Y\x98BP\xbf\x909&\xdc\xc5\xf0\x16\xf1\xd7a\xfd\ +\xe7\xcf`\x0c Z\xa7~\x7f`x\xb8u\xe9\x0a\xe2\ +\x22\x98\xe4\xf4\xb0\x06{\xf7\xaa>D\xa4\xcf\x9c\xb3s\ +\x1e\xaf`\xae{\xd6\xeb`^\xb3&\x0b\x92\x05\x0f\x19\ +u\x0e\xffge\xe3\x0e\xe4!\x22Dk}Ml\x11\ +^}\xf8\x22AW\x170\x84\xbe\x99\xfc\x870\x06z\ +\x03\xb7\x85R\x95Z)N\x99B\xa8\x8d\x93s\xe6(\ +\xa7qc\x16!\x8b|R\xac\x93C\xe1\x5c\xb7\x9a|\ +\x89\xcf\x1d\xd1j\xf5\xc5\xed\x1a\xe1\xd5\x09\xf9\x8e\x90\xa8\ +N|\x84\xa0\xf9a\x18\x03\xbc\xa8\xaa\x1d[t8\x9f\ +:\x95@\x1b\x17\x17-R\xc9f\xcdXx,\xf56\ +\xb10\x07\xc2y\x09\x1d[\x10#\xe3w\xc2\xbd\xcc~\ +9\xf1\x11\x82dxX\x0b\xe1\xa5U\x9d\x9c\xfa\x08\x04\ +\xc16\xfa\xc7Y6nTN\xff\xfe\xca\xc9\xcfg\xc1\ +\xb1\xdc\xc59\x10\xd07\xf39#ri\xd4\x9b\x9f\x8a\ +\xdd\x88\x91\x10\x04\xd5\xc4\xd7\xc3\x18\xd8c\xdc\x0bh\x19\ +O\xca\xa1C\x09\xb7q8g\xae;\xb3T\xaf\xce\x22\ +\x13\x11\xf7\x8aCb\x1c\xce'\xf1\x19#F\xce\xddb\ +\xef\xf0\xea\xc6#\x89\xf4;\x0d\x00YeQ\x18\x03\xba\ +\x8d\xf8fU&d\xaf^\xca\xa9\xac$\xe4F9\x9c\ +\x9f{\xaer\xea\xd7gq\x89\xa0\xbfK\x84\xfe\xd2h\ +`u\xe9->_\xc4H\xfa[\xb1<\xbc\xfaq\x1a\ +q\x12\xb2\x89\xac\xb1\x89\xbf\x85q\xee\xfc\xde\xaaL\xc4\ +v\xed\x94\xa3w^\x09\xb9\xd1\x0c\xe6\x9b6)\xa7{\ +w\x16\x94\x88{K\x22\xfd\xb0X\x5c\xc2y1\xe7\xce\ +\x11#\xef\x0f\xc3;\x8f\xbe[,!VB\xb6\xb8>\ +\x8c\x85peU&`y\xb9r6o&\xe8FQ\ +\xfd\x8b\xc7\xe4\xc9\xca\xa9Q\x83\x85$&.\x8aQ@\ +\xdf\xca\xe7\x89\x18\x0b\xe7\x86WG\xd6\x12+!\x1b\xe8\ +K\x0d\x9f\x9b\x1e\xc0}\xdd3\xac\x19M<\xfdP\xcd\ +\x8a\x15\x04\xdd(\xba~\xbdr\xbave\xf1\x88\x99{\ +\xc4\x1e1\x08\xe7#\xf8,\x11c\xe3\xbbb\x87pj\ +\xc9G\xe2\xe1\xc4K\xa8*\x0f\x98\x1e\xbc\xb5\xc4\xa73\ +\x9dt\xba\xbb\xc7\x82\x05\x04\xdd(:w\xaeJ\x96\x95\ +\xb1p\xc4\xd4G\xdd\xb6\x84Q\x0d\xe7\xf5\xdc\xb3\xab|\ +\x96\x88\xf1\xea\x8f^-\x9c\x9a\xf2\x03\xe2%T\x85\x93\ +\xc3X\x08\xaf\xac\xca\x84\x9b8\x91\xa0\x1b5\xb7mS\ +N\xef\xde,\x169\xe0\xba\x08\x07\xf4\xab\xf8\xfc\x10c\ +\xe9\xaapj\xca\x97b?b&dB\x91\xf8\x96\xe9\ +A{RU&Z\x9f>\x84\xdd\xa8]\x04]\xbc\x98\ +\x0e-9\xa4n\x97: \x82\xe1|\x1c\x9f\x1db\xac\ +\xebR\xffpj\xcb\x13DM\xc8\x849a\xfc\x84\xfc\ +b\xa6\x93\xacI\x93\xf4N,\xa17:N\x9a\xa4\x9c\ +\xa2\x22\x16\x88\x1cS\x1f_\xab\x19\xa1p\xae\xdb\xb1\xbd\ +\xcc\xe7\x86\x18k\x1f\x13\xab\x87Sc\xc6\x107\xc1\x0f\ +\xc5\xe2\x1e\xd3\x03uW\xa6\x93K\x9f[^\xbb\x96\xc0\ +\x1b\x15\xb7lQN\x97.,\x0a\x1cu\x89\x84\xd7\xf0\ +y!\xe6\x84\xcb\xc2\xa91\xcf%x\xbc\x08|0\xdf\ +\xf4 \x1dR\x95\x895g\x0e\xa17*\xae\x5c\xa9\x9c\ +\xa6MY\x0cr\x5c\xdd\xa1\xa9{\x04\xc2\xf9p>+\ +\xc4\x9c\xea6\xd5)\x9cZs2\xb1\x13\xbc\xa0\x1b\xe8\ +;&\x07g\x0d\xf17\x99N\xaa\xc1\x83\x09\xbdQq\ +\xe6L\xe5\x14\x17\xb3\x10\xe0\x7f\xba'\x14Y\x1c\xceK\ +\xab\xd2M\x0a\x11#\xe9\xddb\x81\xf9z\xf3\xa2\x98O\ +\xfc\x84C\xb1\xc8\xf4B\xb8*\xd3\xc9\xa4\x1f#\xda\xbe\ +\x9d\xe0\x1b\x85\x87\x87F\x8dRN^\x1e\x0b\x00~\xc5\ +s,\x0e\xe8\xab\xf9|\x10s\xd2\xb3\xc2\xa99\x93\x89\ +\x9fp0\xca\xc4?\x9a\x1c\x94G\x8a\xefg2\x89\x8a\ +\x8aT\xf2\x92K\x08\xbf\xb6\xbbu\xabr:v\xa4\xe8\ +\xe3\x01}Glna8\xef\x9ai]B\xc4\xc8\xfb\ +\x96\xd8\xc4|\xddyM, \x86\xc27\xb1\xd4\xf4B\ +\xf8\xa3L'\xd1\xf8\xf1\x84_\xdb\xbd\xec2\xce\x9b\xe3\ +!\xbd\xde\xb2p\x9e'\xde\xc5\xe7\x82\x98\xd3V\x86S\ +\x7f\xa6\x11C\xe1\x9b:\xb7\x18={>:\xc3\x89\x93\ +j\xd3F9\x15\x15\x04`\x9b\xfb\x9b\xafX\xa1\x9c\x06\ +\x0d(\xf4\xe8\xc9\x81\x16\x05\xf4\x09|\x1e\x88\xf4F\x17\ +{\x84\xb3\x8b\xceYt\xf8\x1a\xb3L\x0eD\xf96\xa0\ +\x9e\xcc$\x9cW\xaf\xae\x92\xb4T\xb4\xdb\xb9s\xb9\x0c\ +\x8a\xbe|@,\xb4 \x9c\xeb\x0b\xeb\xcf\xf1y \xa2\ +\xf8s1\xdf|\x1d\x1aK\x1c\x85\xfd\xd1=8_6\ +9\x08\xe7g:i&L \x00\xdb\xec\xacY*Y\ +XHqG\xdf\xce\xb0 \xa0/\xe1s@\xc4\xfd\x9c\ +d\xbe\x0e=L$\x85\xfd9\xd1\xe4\x00\xd4/\xf3\xbd\ +\x91\xc9di\xdd:\xdd\x11\x84 l\xef\xcb\xa0tj\ +\xc1\x0c\xd5\xafu\xd6\x0a1\x9c\xebKa\xef\xf29 \ +\xe2~>\xef\xb6\x5c5\x5c\x8fz\x11K\xe1\xdf<h\ +r\xf0m\xc9\xb0k\x8b\xa3\xcf5\x13\x84\xed\xf4\xe4\x93\ +\x09\xe7Xe/\x0a1\xa0o\xe1\xef\x8f\x88\x07\xf0B\ +\xf3\xf5\xe8Vb)hz\x9a\x1cx-\x12\xe9\xd7\xba\ +|O\x92\xd1\xa3\x09\xc1\xb6\xaa?\x1b\x8a8f\xc17\ +\xc5\x86!\x84\xf3\xd6\x99\xd6%D\x8c\xbd\xfa\x17\xffz\ +fk\xd2\xe7bK\xe2)\xdcjr!\xac\xc8d\x82\ +\x94\x97\xab\xd4\xce\x9d\x04a\x1b\x1d;\x96\x02\x8eYu\ +]\x08\x01\xfd\x1a\xfe\xee\x88x\x10\x97\x9b\xafK;\x89\ +\xa7\xb9M3\xf7\x9b\x9a\x91\x01\xd76\x91\xe1\xe3\x1f\xf3\ +\xe6\x11\x84\x09\xe7\x98#\xee\x16\x9b%\xcc>J\x94\xe4\ +\xef\x8e\x88\x89\x83?^d\xf8\xd7\xbd\xbf\x8b\xb5\x89\xa9\ +\xb9\xcbZ\x93\xdf\x08\xaf\xcd\xa4\xadb\xd7\xae\x04a\x1b\ +\xfb\x9c\x8f\x1bG\xd1\xc6\xc0\xdcn\xb0.}\x8f\xbf7\ +\x22\xda\xf9\xeb\xde\xb9\xc4\xd4\xdc\xa4HL\x99\x1ahG\ +e\xb0K\xa5\xdb\xf5\xa5V\xaf&\x10\xdb\xa6nuI\ +\xb1\xc6\x00\xd5\xbf\xb4\xb54P\x97\xba\xf1\xb7FDK\ +\x7f\xdd\x13_ \xaa\xe6&F[+^\x97\xc9\x848\ +\xf6X\xc2\xb0m\x9e~:\xddZ\xd0\x88\x1b\x0d\xd4\xa5\ +\xab\xf9;#\xa2\x0f\xd7\x9b\xdfE?\x86\xb8\x9a{\xdc\ +a\xb2C\xc2^\xbf\x13\xa1F\x0d\xe5l\xdeL \xb6\ +\xc99sT2?\x9f\x22\x8dF|\xcf\xedM\x1eT\ +]j\x97I]B\xc4\x9c\xf6\x1d\xb1\xbe\xd9\x80~5\ +q5\xb78L\xfc\xcc\xd4\x00\xdb\x94\xc9D\x988\x91\ +@l\x91\xc9\x85\x0b\xd3\xbd\xe8)\xd0h\xd0\xcb\x02\xac\ +KW\xf0\xf7E\xc4\x0c\x5cd6\xa0\x7f(\x96\x11[\ +s\x87U\xa6\x06W\xb9\xbb\x13\xe6k\x024h\xa0\x9c\ +]\xbb\x08\xc6\xb6\xb8l\x99r\xaaW\xa70c(\xbb\ +\xe8\xe5\x01\xd4\xa5V\xec\x9e#b\x86\xbe\x920\xfe\xba\ +\xe8\xd9\xc4\xd6\xdc\xa0@|\xdf\xd4\xc0\xba(\x93\x090\ +e\x0a\xa1\xd8\x16\xd7\xadS\xa9:u(\xca\x18\x9a\x17\ +'x5\x14\x11\xedr\x86\xd9\x80\xfe,\xd157\x18\ +ajPU\x17_\xf4;\xf0\xcb\xcb\x95SQA0\ +\xb6\xc1m\xdb\x94s\xc4\x11\x14c\x0c}\xb7\xaa,\x8b\ +u\xa9\x91\xf8.\x7fWD\xac\x82\x8f\x8a\xf9fCz\ +g\xe2k\xfc\xb9\xd1\xd4\x80\x9a\x91\xc9\xc0\x9f6\x8d`\ +lC\x9fs\xf9\x92\x94\xea\xd4\x89B\x8cVxN\x16\ +\xeb\xd2\xa5\xfc=\x111\x0b\x9eh6\xa0o$\xbe\xc6\ +\x9bb\xf1\xaf&\x06S\x9e\xf8\x88\xcf\xc1\x9el\xd4h\ +_0$ [\x10\xd0G\x8e\xa4\x00\xa35>'\x16\ +e\xa1.\xd5\x12_\xe3\xef\x89\x88Y\xf0'f\x03\xfa\ +\x9bD\xd8xs\x92\xa9\xc14$\x83\xc1\x9e\x9c>\x9d\ +plI;Ez\x9d\xa3mN\xcdB]:\x9f\xbf\ +#\x22f\xd1NfCzObl|\xf9\xbe\xa9\x81\ +tU&g\xcf++\x09\xc7a\xbbt)\xed\x14\xd1\ +J\x1f\xa9\xe2\x99\xcfb\xf1\xb7\xfc\x1d\x111\x8b\xae6\ +\x1b\xd07\x11c\xe3I\xa9\xf8\x91\x89A\xd4 \x91~\ +\x12\xd7\xcf O\x9dv\x1a\xe18l\xf5\xc3P\xf5\xeb\ +St\xd1Z\xc7\x9a\xbe\x13\x83\x88x\x10\xf5\x91\xb9\x12\ +s\x01}\x8f\x98G\x9c\x8d\x1f\x13M}\xcb\x9b\xe7\xf7\ +hKY\x99J\xed\xd8A@\x0e\xd3\x8a\x0a\x95\xec\xd0\ +\x81\x82\x8bV{\x9f{\xbf\xc5oM\xd2\xe7\xd7\x9f\xe1\ +\xef\x87\x88\x018\xc1\xec.z?\xe2l\xfc\xb8\xcd\xd4\ +\xe5\xd0G\xfd\x0ep}!\x91\x90\x1c\xae\xe3\xc6Qh\ +1\x12\x0e\xcd\xa0.M\xe4\xef\x86\x88\x01\xf9#\xb3\x01\ +}'q6^\x94\x88\xff01xz\xf9\x1d\xdcE\ +E*\xb5i\x13\x019\xcc\x8e-\x8b\x17\xabd~>\ +\x85\x16#\xe1-\x19l\x1a\xdc\xc7\xdf\x0d\x11\x032)\ +6\xe7\x98\x0bd\xc8\xf1\xa6\xbe\xddm\xf5;\xb8\x07\x0c\ + $\x87\xe9\xd6\xad\xcai\xd0\x80\x22\x8b\x91\xb2\x9b\x8f\ +\x9at,\x7f/D\x0c\xd8\x0b\xcd\xee\xa2\x1fE\xac\x8d\ +\x0f\x15&\x06M\xb5Lz\x0c/[FH\x0eS\xfd\ +\x05\x89\xe2\x8a\x11\xf3z\x1fu\xe9g\xfc\xbd\x101`\ +\x9f\xc8\xf0~L\x86^B\xac\x8d\x0f\xef\x98\x184\xc3\ +\xfd\x0e\xea\x96-\x09\xc8a:s&\x85\x15#\xfb\x93\ +r{\x0f5\xa97\x7f+D\xb4\xf0\x97\xbd*\xfa\x08\ +\xb16\x1e\xb46\xf5\xb3\xcb\x0e\xbf\x03z\xca\x14Br\ +H&\xd7\xaeUNI\x09E\x15#\xeb\x16\x0f5\xe9\ +;\xfc\x9d\x10\xd1\x90\x97\x98\x0b\xe8\x9f\x8a\xb5\x88\xb7\xd1\ +g\x81\x89\x01S]|\xc3\xcf`..VI}\xfe\ +\x99\xb0\x1c\x8e]\xbbRP1\xd2\xea\xb7\x16\x0e?H\ +M\xea\xcc\xdf\x08\x11\x0d\xfa\x8c\xd9c.\x13\x89\xb7\xd1\ +\xe7\x17&\x06\xcb\xf1>\x07rj\xe0@BrXN\ +\x9fN1\xc5X\xb8\xe6 5\xe9\x0a\xfe>\x88h\xd8\ +\x1e\xe6\x02\xfa\xb5\xc4\xdbhSl\xaa\xbdb\xa5\xdf\x81\ +\xac\x9f\x94',\x9bw\xe3F\xe5\x94\x96RH1\x16\ +\xea_\xed\xea\x1c\xa0\x1e\x1d\x9e\xf0\xff\x9a1\x22bU\ +]a.\xa0\xef&\xe2F\x9b\xe1&\x06\x8a~\xa5\xef\ +u?\x83\xb8iS\x82rX\xf6\xe9C\x11\xc5X\xb9\ +\xf0\x005i-\x7f\x17D\x0c\xc1'\xcd\xb6[\xecD\ +\xcc\x8d.\x1bL\x0c\x92~~\x07\xf1I'\x11\x94\xc3\ +\xb8\x18z\xd6Y\x14P\x8c\x9d/\x8a%\xfb\xd5\xa3z\ +\xe2\xdb\xfc]\x101$[\x9b\x0b\xe8\xf3\x89\xb9\xd1\xe5\ +1\x13\x83\xe4R\xbf\xe7\xcfW\xaf&0\x9bv\xfbv\ +\xe5\xd4\xafO\xf1\xc4X:g\xbfz\xb4\x94\xbf\x07\x22\ +\x86\xe8Y\xe6\x02\xfa\xad\xc4\xdchR]\xfc\xc4\xc4 \ +\xf9\xb5\x9f\xc1\xdb\xa2\x05a9\x0cG\x8e\xa4pbl\ +}\xd6=jW\xcb\xefq;D\xc4,{\xb3\xb9\x80\ +\x9e$\xeaF\x93\xbe&\x06H\xe3D\xfa\xd1\x10\xcf\x83\ +w\xc2\x04\xc2\xb2i\xd7\xacQNQ\x11\x85\x13c\xed\ +Dw\xe7\x8a\xbf\x05\x22\x86\xe9;\x89t\xebiC!\ +\xbd9q7z,218N\xf33p\xf3\xf2\x94\ +\xb3n\x1d\x81\xd9\xf4\xd9\xf3\xee\xdd)\x9a\x18{\x1fp\ +w\xd2\xf9[ b\xd8\x1ek.\xa0O&\xeeF\x8f\ +\xdbM\x0c\x8ek\xfc\x0c\xdaV\xad\x08\xcc\xa6]\xb8\x90\ +b\x89\x88\x88h\xd0\xb5\xe6\x02z%q7z\xfc>\ +\xe8\x81Q \xbeF\xf7\x16{\xad\xacT\xa9\x96-)\ +\x96\x88\x88\x88\x06}\xc4\x5c@\x7f\x9e\xb8\x1b-\xda\x99\ +\x18\x18\x9d\xfc\x0e\xdaK.!4\x9b<\xda\xc2\x8b\xa1\ +\x88\x88\x88\xa1Xn&\xa0\x7f!\xd6!\xf6F\x87\xa9\ +&\x02\xfa4?\x83\xb5^=B\xb3AS;w\xaa\ +\x94\xfe\x9bS$\x11\x11\x11\x8d{\xbc\xb9]\xf4\xe1\xc4\ +\xde\xe8\xb0\xcd\xc4\xa0\xb8\xd2\xcf`\x1d0\x80\xe0lr\ +\xf7|\xd2$\x0a$\x22\x22bH\xae2\x17\xd0/\x22\ +\xf6F\x87_\x99\x18\x14O\xfb\x19\xacs\xe6\x10\x9c\x0d\ +>J\x94\xaa]\x9b\x02\x89\x88\x88\x18\x92?7\x17\xd0\ +o$\xf6rA\xf4?\x96\xfb\x19\xa8\x85\x85*\xb9u\ ++\xc1\xd9\x94\xe3\xc7S\x1c\x11\x11\x11Ctw\xc2X\ +?t.\x8aF\x84\xc6&\xbe\xb1\x8d\xf53P\xdb\xb6\ +%4\x1b\xdc=O\xd6\xacIqDDD\x0c\xd9\xbe\ +f\x02\xfa\xa7b5\xe2\xaf\xfd\x1cg\x22\xa0\xaf\xf23\ +HO8\x81\xe0l\xca\xb1c)\x8a\x88\x88\x88\x168\ +\xcf\xdc1\x97N\xc4_\xfb1\xf2\x82\xe8m~\x06\xe9\ +\x82\x05\x04gC\xbb\xe7Ni)E\x11\x11\x11\xd1\x02\ +\xaf4\x17\xd0O'\xfe\xda\xcfwM\x0c\x86W<\x0e\ +\xced~~:8\x12\xa0\x83\xf7\xb4\xd3(\x88\x88\x88\ +\x88\x96\xf8\x80\xb9\x80\xbe\x81\xf8k?\xcfXuA\xf4\ +\x88#\x08\xce\x86^\x0du\x1a5\xa2 \x22\x22\x22Z\ +tQ\xb4\xc8L@\xbf\x8b\xf8k?\x7f\x0fz \x0c\ +\xf63@\x87\x0c!<\x9b\xe8{~\xd6Y\x14CD\ +DD\xcb\xech&\xa0\xbfE\xfc\xb5\x9b\x86&~J\ +\x99\xebgp\xce\x9cI\x806\xa1\xee\x94C!DD\ +D\xb4\xca\x93\xcdur) \x06\xdbKo\x13\x01\xbd\ +\xc2\xc7\xc0L\xae]Kx\x0e\xda\x8b/\xa6\x08\x22\x22\ +\x22Z\xe8rs\xe7\xd0\x9b\x13\x83\xed\xe5T\x13\x83\xe0\ +W^\x07\xa6\xee(B\x80\x0e\xde\xbe})\x82\x88\x88\ +\x88\x16\xfa}s\x01}\x101\xd8^\x96\x04=\x00\xf2\ +\xc4\xb7\xbd\x0e\xcc\xf6\xed\x09\xcfA{\xf9\xe5\xca)*\ +\xa2\x08\x22\x22\x22Z\xe8\x93\xe6\x02\xfa4b\xb0\xbd\x5c\ +\x1d\xf4\x00h\xe4g`\x0e\x1dJ\x80\x0e\xfar\xe8\xa4\ +I\x14@DDDK\xddc\xae\x93\xcb*b\xb0\xbd\ +\xdc\x1b\xf4\x00\xe8\xe1g`N\x99B\x88\x0e\xda\xc3\x0e\ +\xa3\x00\x22\x22\x22Zl33\x01\xfd\x06b\xb0\xbd\xbc\ +\x11\xf4\x008\xc9\xc7\x80L-YB\x80\x0e\xd2\x8b.\ +\xa2\xf0!\x22\x22Zn\x7f3\x01\xfd!b\xb0\x9d\xe4\ +\x89\x1f\x07=\x00\xce\xf5: \xf3\xf3Uj\xc7\x0eB\ +t\x90\xf6\xefO\xe1CDD\xb4\xdcS\xcd\x04\xf4\xf7\ +\x88\xc2vR\xd7\xc4%\x84M^\x07\xa4~\xd5\x92\x10\ +\x1d\x9c\xdb\xb7+\xa7\xa4\x84\xc2\x87\x88\x88h\xb9\x8b\xcd\ +\x04\xf4O\x88\xc2v\xd2\xc6D@\xbf\xc9\xeb\x80\xec\xd4\ +\x89\x10\x1d\xa4\xfa\x01(\x8a\x1e\x22\x22\xa2\xf5\xee2\xd7\ +\xc9\xa5\x8c8l\x1f}L|\xf8\x0f{=\x7f>x\ +0!:H\x8f:\x8a\xa2\x87\x88\x88\x18\x01\x7fd.\ +\xa0\xb7 \x0e\xdb\xc7\x89&>\xfc\x97\xbd\x0e\xc8\xf1\xe3\ +\x09\xd1A\xb9u+\xbd\xcf\x11\x11\x11#\xe2\x03\xe6\x02\ +\xfa1\xc4a\xfb\x98\x16\xf4\x07_ \xee\xf5\xba\x83>\ +{6A:(\xa7O\xa7\xe0!\x22\x22F\xc4\xdf\x9a\ +\x0b\xe8#\x89\xc3\xf6\xb1(\xe8\x0f\xbe\x9e\x9f\x01\xb9t\ +)A: S]\xbbR\xf0\x10\x11\x11#\xe2\xeeD\ +\xfa%v\x03\x01\xfd\x0c\xe2\xb0}\xac\x0f\xfa\x83o\xed\ +g@n\xdeL\x98\x0e\xc2-[T\xb2\xb0\x90\x82\x87\ +\x88\x88\x18!k\x99\x09\xe8\x0b\x88\xc3\xf6qu\xd0\x1f\ +|O\xaf\xc7[\xaaW'H\x07\xb5{N\xf7\x16D\ +D\xc4\xc8\xd9\xc2L@_M\x1c\xb6\x8f\xdb\x82\xfe\xe0\ +Gx\x1c\x84Iz\xa0\x07g\xcf\x9e\x14:DD\xc4\ +\x88y\xb4\x99\x80^A\x1c\xb6\x8f_\x04\xfd\xc1\x9f\xea\ +u \xb6lI\x90\x0e\xc2\xcaJ\xe5\x94\x95Q\xe8\x10\ +\x11\x11#\xe603\x01\xfdz\xe2\xb0}\xdc\x17\xf4\x07\ +?\xcb\xeb@\xec\xd2\x850\x1d\x84\x17^H\x91CD\ +D\x8c\xa0c\xcd\x04\xf4\x1f\x10\x87\xed\xe3\xe1\xa0?\xf8\ +y^\x07b\x9f>\x84\xe9 \x1c=\x9a\x22\x87\x88\x88\ +\x18A'\x9a\x09\xe8\xb7\x11\x87\xed\xe37A\x7f\xf0\xe7\ +y\x1d\x88\xc3\x86\x11\xa6\x83\xb8 \xaa\x8f\x0eQ\xe4\x10\ +\x11\x11#\xe7\xe9f\x02\xfa\x9d\xc4a\xfbx>\xe8\x0f\ +~\xb1\xd7\x818v,\x81:\xdb\xea\xb6\x95\xf9\xf9\x14\ +9DD\xc4\x08:\xc3L@\xbf\x978l\x1f/\x07\ +\xfd\xc1/\xf3:\x10O?\x9d@\x9dm\xe7\xcc\xa1\xc0\ +!\x22\x22F\xd49f\x02\xfa\x03\xc4a\xfbx+\xe8\ +\x0f~\x95\xc7A\xb8\xafW7\xa1:\xab&\x8f;\x8e\ +\x02\x87\x88\x88\x18Q\xcf5\x13\xd0\x1f'\x0e\xdb\xc7\x9e\ +\xa0?\xf8u^\x07\xa2\xde\xed%Ts\xfe\x1c\x11\x11\ +\x11\xf7y\x81\x99\x80\xfe\x0cq\xd8>RA\x7f\xf0\x97\ +{\x1d\x88s\xe7\x12\xaa\xb3\xe9\xf6\xed\xca)(\xa0\xc0\ +!\x22\x22F\xd4%f\x02\xfa\x0b\xc4a\xfbp\x82\xfe\ +\xe07{=\xe22\x7f>\xa1:\x9b\xc7[\x16.\xa4\ +\xb8!\x22\x22F\xd8\x0b\xcd\x04\xf4\xdf\x12\x87s\xf0\x88\ +\xcbz\xaf\x03Q\x07J\x82u\xf6\x8e\xb7\x8c\x1bGq\ +CDD\xe4\x88\x0bG\x5c\x22\xc8;A\x7f\xf0k\xbd\ +\x0e\xc4\xc5\x8b\x09\xd6\xd9\x0c\xe8]\xbbR\xdc\x10\x11\x11\ +#\xec\x023\x01\xfd\x09\xe2\xb0}\xbc\x11\xf4\x07\xbf\xd2\ +\xeb@\x5c\xba\x94`\x9dMk\xd7\xa6\xb8!\x22\x22F\ +\xd8yf\x02\xfa#\xc4a\xfbx%\xe8\x0f~\xb9\xd7\ +\x81\xb8l\x19\xa1:\x9b\x0f\x14Q\xd8\x10\x11\x11\xe9\x83\ +\x9e\xa0\x0fz\x14y1\xe8\x0f~);\xe8\xe6=\xef\ +<\x0a\x1b\x22\x22b\xc4\x9di&\xa0\xff\x928l\x1f\ +\xcf\x07\xfd\xc1/\xf6:\x10/\xba\x88`\x9d-O9\ +\x85\xc2\x86\x88\x88\x18q\xcf4\x13\xd0\x7fA\x1c\xb6\x8f\ +\xa7\x83\xfe\xe0/\xf0\xdaf\x91K\xa2\xd9k\xb1\xd8\xaf\ +\x1f\x85\x0d\x11\x111\xe2N6\x13\xd0\xef \x0e\xdb\xc7\ +\xe3A\x7f\xf0s=\x0e\xc2$m\x16\xb3g\x8b\x16\x14\ +6DD\xc4\x88;\xd6L@\xbf\x8d8l\x1f\xbf\x0a\ +\xfa\x83\x9f\xeau \x9e\x7f>\xc1:\x1bVV*\xa7\ +\xb8\x98\xc2\x86\x88\x88\x18q\x8f5\x13\xd0\xaf'\x0e\xdb\ +\xc7O\x82\xfe\xe0'x=\xe2\xc2K\xa2\xd9q\xdd:\ +\x8a\x1a\x22\x22b\x0c\xeci&\xa0\xef$\x0e\xdb\xc7\x8d\ +A\x7f\xf0#\xbc\x06\xf4s\xce!\x5cg\xc3\x0b.\xa0\ +\xa8!\x22\x22\xc6\xc0\x8ef\x02\xfae\xc4a\xfb\xb82\ +\xe8\x0f~\x80\xd7\x80>{6\xe1:\x1bN\x9bFQ\ +CDD\x8c\x81\xcd\xcc\x04\xf4%\xc4a\xfb\xd8\x1c\xf4\ +\x07\x7f\xb4\xd7K\xa2S\xa7\x12\xae\xb3\xe1\xe8\xd1\x145\ +DD\xc4\x18X\xcfL@\x9fK\x1c\xb6\x8f\x15A\x7f\ +\xf0\xed\xbc\x0e\xc4I\x93\x08\xd7\xd9\xb0o_\x8a\x1a\x22\ +\x22b\x0c\xacf&\xa0O%\x0e\xdb\xc7\x05A\x7f\xf0\ +M\xbd\x1eq\x197\x8ep\x9d\x0d\xdb\xb6\xa5\xa8!\x22\ +\x22F\xdcw\xcc\x84s\xed8\xe2\xb0}\xcc\x09\xfa\x83\ +/\xf1:\x18G\x8d\x22\x5cg\xc3\xfa\xf5)l\x88\x88\ +\x88\x11\xf77\xe6\x02\xfa\xb1\xc4a\xfb\x98d\xe2\xc3\x7f\ +\xdb\xcb`\x1c:\x94p\x9d\x8dWD\x0b\x0b)l\x88\ +\x88\x88\x11\xf7\xe7\xe6\x02z7\xe2\xb0}\x0c5\xf1\xe1\ +?\xe5e0\xea\xe7\xe9\x09\xd8Us\xdb6\x8a\x1a\x22\ +\x22b\x0c\xbc\xc1\x5c@oL\x1c\xb6\x8f.&>\xfc\ +\xbb\xbd\x0c\xc6n\xdd\x08\xd8Uu\xcd\x1a\x8a\x1a\x22\x22\ +b\x0c\xdcb&\x9c\x7f!\x16\x10\x87\xed\xa3\xb1\x89\x80\ +\xfe}/\x97D\xdb\xb4!`W\xd5%K(j\x88\ +\x88\x881p\xa9\x99\x80\xfeG\xa2\xb0\x9d\x14\x89_\x06\ +=\x00vy\x19\x8c\xe5\xe5\x04\xec*\x9a:\xf7\x5c\x8a\ +\x1a\x22\x22b\x0c\xfc\x96\x99\x80\xfe\x12Q\xd8^\xfe\x1a\ +\xf4\x00X\xe5e0\x96\x96\x12\xb2\xab\xea\xf4\xe9\x145\ +DD\xc4\x188\xceL@\xff51\xd8^\xde\x08z\ +\x00\xcc\xf32\x18\xf3\xf2\x94SQA\xc8\xae\x8a\xa7\x9c\ +BQCDD\x8c\x81=\xcd\x04\xf4\x9b\x89\xc1\xf6\xf2\ +X\xd0\x03\xe0$\x8f\x831\xb5i\x13!\xbb*\x8e\x19\ +CQCDD\x8c\x81\x8d\xcd\x04\xf4\x9d\xc4`{\xf9\ +i\xd0\x03\xa0\x97\xd7\x01\xb9|9!\xbb*\x1e\x7f<\ +E\x0d\x11\x111\xe2\xee\x16\xf3\xcd\x04\xf4\xa5\xc4`{\ +\xb9\x22\xe8\x01\xd0\xd4\xeb\xa0\x5c\xb0\x80\x90]\x95K\xa2\ +#FP\xd8\x10\x11\x11#\xee\xe3\x09c=\xd0O#\ +\x06\xdb\xcb\xd2\xa0\x07@\x81\xb8\xc7\xcb\xa0\x9c:\x95\xa0\ +]\x15\x8f=\x96\xc2\x86\x88\x88\x18qo5\x17\xd0\xfb\ +\x10\x83\xed\xe5t\x13\x83\xe0\x19/\x83r\xf4hBv\ +Uv\xd0\x07\x0f\xa6\xb0!\x22\x22F\xdcm\xe6\x02z\ +\x13b\xb0\xbd\x0c21\x08\xee\xf20 \x93\xfd\xfa\x11\ +\xb4\xab\xe0\xbe\xbf\x1f\x85\x0d\x11\x111\xd2^`&\x9c\ +\x7f\x22\xe6\x13\x83\xed\xa5\x85\x89\x80~\x95\x97A\xd9\xb1\ +#A\xbb*\xf6\xeeMaCDD\x8c\xb8c\xcd\x04\ +\xf47\x89\xc0v\xa3_\x13\xfd\x22\xe8\x81p\x91\x97A\ +\xd9\xa4\x09!\xbb*G\x5cz\xf6\xa4\xb0!\x22\x22F\ +\xdc\x8ef\x02\xfa}D`\xfb\xd9\x1b\xf4@\x98\xe8a\ +@\xa6\xaaW'h\xb3\x83\x8e\x88\x88\x98\xb3\xbe/\x16\ +\x9b\x09\xe8\xd7\x11\x7f\xed\xe7\xf1\xa0\x07Bw\xaf\x83s\ +\xe3F\x826g\xd0\x11\x11\x11i\xb1\x18\xac\x97\x10\x7f\ +\xed\xe7\x07A\x0f\x84\xda^\x07\xe7\x05\x17\x10\xb63u\ +\xd0 \x8a\x1b\x22\x22b\x84\xbd\xc1\x5c@?\x99\xf8k\ +?+L\x0c\x86\x17\xbc\x0c\xce3\xce hg\xea\xd0\ +\xa1\x147DD\xc4\x08\xbb\xdc\x5c@\xefH\xfc\xb5\x9f\ +\xc9&\x06\xc3\x1d^\xce\xa1\xeb\xd70\x09\xdb\x99\x1dq\ +9\xee8\x8a\x1b\x22\x22b\x84=\xcdL8\xffL\xac\ +F\xfc\xb5\x9f\x1e&\x02\xfav/\x83\xb3[7\xc2v\ +\xa6\x8e\x1cIqCDD\x8c\xb0\x9d\xcd\x04\xf4\xd7\x88\ +\xbe\xd1\xa0\xa6\xf8e\xd0\x03\xe2,/;\xe8\xb4Z\xcc\ +\xdcq\xe3(n\x88\x88\x88\x11u\xb7Xd&\xa0\xff\ +\x84\xe8K\xab\xc5\xff8\xc0\xcb\x00-*RNE\x05\ +a;\x93>\xe8\x93'S\xe0\x10\x11\x11#\xea\xdd\xe6\ +\xce\x9f\xaf#\xf6F\x87\x07\x83\x1e\x10\xf5\xbc\x0e\xd2\xe5\ +\xcb\x09\xdc\x998k\x16\x05\x0e\x11\x111\xa2n1\x17\ +\xd0\xcf$\xf6F\x87kL\x0c\x8a\xe7\xbc\x0c\xd2\x193\ +\x08\xdb\x998\x7f>\x05\x0e\x11\x111\xa2N3\x17\xd0\ +\x8f&\xf6F\x87\x85&\x06\xc5\x8dtr\x09\xce%K\ +(p\x88\x88\x88\x11\xb5\xbb\x99p\xfe\x09\x1d\x5c\xa2\xc5\ +\xb1&\x02\xfa\xc5^\x06i\xc7\x8e\x84\xedL\x5c\xbd\x9a\ +\x02\x87\x88\x88\x18\xd1\x0b\xa2\xd5\xcd\x04\xf4g\x88\xbc\xd1\ +\xa2\xbe\x89\x80>\xd6\xcb@\xad]\x9b\xb0\x9d\x89[\xb6\ +P\xe4\x10\x11\x11#\xe8\xcf\xcd\x1do\xb9\x86\xc8\x1b=\ +\xf6\x04=0Zy\x1c\xa8\xa9\x8d\x1b\x09\xdc\x99tr\ +\xa9^\x9dB\x87\x88\x88\x181W\x99\x0b\xe8s\x89\xbb\ +\xd1\xe3\xae\xa0\x07F\x9e\xf8\xb2\x97\x80~\xee\xb9\x04\xee\ +L,/\xa7\xd0!\x22\x22F\xcc\xd1\xe6\x02zo\xe2\ +n\xf4\xb8\xcc\xc4\xe0\xf8\x9e\x97\xc1z\xc2\x09\x84\xedL\ +l\xdf\x9eB\x87\x88\x88\x181\x1b\x99\x09\xe7\x9f\x89%\ +\xc4\xdd\xe81\xd1D@?\x8f\x8b\xa2\xc1\xd9\xbb7\x85\ +\x0e\x11\x111B>nn\xf7\xfc\x05\xa2n4ik\ +b\x80xzQ\xb4\xa4D9\x95\x95\x04n\xbfg\xd0\ +G\x8e\xa4\xd8!\x22\x22F\xc8\x1d\xe6\x02\xfauD\xdd\ +h\x92'\xfe%\xe8\x01R&\xbe\xefe\xd0\xaeXA\ +\xe8\xf6\xeb\xa4I\x14;DD\xc4\x08y\x9a\xb9\x80>\ +\x93\xa8\x1b]\xee11H\xee\xf32h\xa7L!p\ +\xfb\xddA?\xe7\x1c\x8a\x1d\x22\x22b\x84<\xcc\x5c@\ +oG\xcc\x8d.\xabL\x0c\x92\xf5^\x06\xed\xc0\x81\x84\ +n\xbf\xaeZE\xb1CDD\x8c\x88\x8f\x98\x0b\xe7\x7f\ +pOJ@D\x19eb\xa0\x9c\xe8e\xe0\xea\x96\x81\ +\x84n\x7fVT\xa8da!E\x0f\x11\x111\x02\xae\ +3\x17\xd0\x7fL\xc4\x8d6u\xc5/\x83\x1e(\xf2\x1f\ +\xa2\xf6z\x19\xbc\xeb\xd6\x11\xba\xe9\x85\x8e\x88\x88\x18K\ +G\x9a\x0b\xe8\x17\x10q\xa3\xcf\xcb&\x06\xcb=^\x06\ +\xef\xb4i\x04n\xbf\xe7\xd0\xbbv\xa5\xe8!\x22\x22Z\ +\xeen\xb7q\x86\xa1\x80~\x0c\xf16\xfa\x5cob\xb0\ +\xac\xf02\x80\xfb\xf6%t\xfbu\xd80\x0a\x1f\x22\x22\ +\xa2\xe5\xdea.\x9c\xffC,\x22\xdeF\x9f9&\x06\ +\xcc0/\x03\xb8A\x03\x02\xb7_O?\x9d\xc2\x87\x88\ +\x88h\xb9\xe7\x99\x0b\xe8w\x13m\xe3\xc1\x91&\x06L\ +\xa9\xfb\xf3\xce\xa1\x06pj\xf5jB\xb7\x1f/\xba\x88\ +\xc2\x87\x88\x88h\xb9\x1d8\x7f\x0e>\xd1mxR&\ +\x06\xcd\x8f\xbd\x0c\xe2\xc9\x93\x09\xdd~\xdc\xbe]9y\ +y\x14?DDDK}\xdc\x5c8\xd7v&\xda\xc6\ +\x87\x1f\x98\x184\xf3\xbc\x0c\xe4\xce\x9d\x09\xddtrA\ +DD\x8c\x8d\xab\xcc\x85\xf3$\xfd\xcf\xe3\xc5\x0c\x13\x03\ +\xa7\x8d\x97\x81\x5cT\x94\xde\x15&x{6\xd9\xbd;\ +\x05\x10\x11\x11\xd1R{\x99\x0b\xe8\xd7\x13i\xe3EK\ +S?\xbd\xfc\xc6\xcb`\x9e7\x8f\xe0\xed\xc7\xb1c)\ +\x80\x88\x88\x88\x16\xfa\xb2X`.\xa0\x9fA\xa4\x8d\x1f\ +o\x9b\x18<\xeb\xbc\x0c\xe8!C\x08\xdd~<\xfbl\ +\x8a \x22\x22\xa2\x85n7\x17\xce\xf5\xc3\x93\xe5\xc4\xd9\ +\xf8\xf1?\xb6\xb4[L\xd5\xabG\xe8\xf6\xe3\xc6\x8d\x14\ +ADDD\x0b\x1dd.\xa0?G\x94\x8d'\x93M\ +\x0c\xa0\xea\xe2\x9b^\x06\xf5\xf2\xe5\x04o?\xd6\xafO\ +!DDD\xb4\xc8\xdf\x89\x85\xe6\x02\xfaJ\xa2l<\ +\xa9'~nb\x10Uz\x19\xd8\xc7\x1fO\xe8\xf6a\ +\xaagO\x8a!\x22\x22\xa2E\xae5\xdb^\xb1\x0bQ\ +6\xbe<ab\x10\x8d\xf60\xa8\x93\x8d\x1a\x11\xbc\xfd\ +8i\x12\xc5\x10\x11\x11\xd1\x22{\x9a\x0b\xe7\xef\x12a\ +\xe3\xcd\xc5&\x06R\xb1\xf8\xba\x97\xc1}\xc9%\x04o\ +\xaf;\xe8K\x96P\x0c\x11\x11\x11-\xf1I1\xcf\x5c\ +@\xdfJ\x84\x8d7G\x99\xfa)\xe6j\x8e\xb9d\xd7\ +]\xbbT\xaaZ5\x8a\x22\x22\x22\xa2\x05.7{\xbc\ +e\x08\x116\xde\xe8\xd7\xa7\xde71\x98\xc6z\x19\xe0\ +M\x9a\x10\xbc\xfd\xd8\xba5E\x11\x11\x11\xd1\x02;\x9a\ +\x0b\xe7\xff+\x16\x12a\xe3\xcf\xd5&\x06T\x0d\xf1m\ +/g\xd19\xe6\xe2\xddQ\xa3(\x8a\x88\x88\x88!\xfb\ +\x0b\xb3\xbb\xe7\xdf!\xba\xe6\x06cM\x0d\xaa\xab\xbc\x0c\ +\xf4a\xc3\x08\xde^]\xb0\x80\xc2\x88\x88\x88\x18\xb2g\ +\x9a\x0d\xe8#\x89\xae\xb9A\x89\xf8w\x13\x83\xea8/\ +\x03\xbdf\xcd}\xe7\xab\x09\xe0\x1e\xdc\xb1C9EE\ +\x14GDD\xc4\x90\xd4\xa7\x03j\x99\x0b\xe7\x7f\xe4x\ +Knq\xb3\x89\x81\xa5\x9b\xf7\xff\xd6\xcb\x80\x9f;\x97\ +\xf0\xed\xd56m(\x90\x88\x88\x88!\xb9\xcb\xec\xee\xf9\ +\x15D\xd6\xdc\xe2$S\x83k\xb9\x97\x01\xdf\xbd;\xc1\ +\xdb\xab'\x9c@\x81DDD\x0c\xc9^f\x03z_\ +\x22knQC\xfc\x87\x89\xc1\xd5\xd1\xcb\x80\xd7\xc76\ +.\xbf\x9c\xf0\xed\xc5\xf3\xce\xa3@\x22\x22\x22\x86\xe0#\ +\x09\xa3\xbd\xcf\xf7\x88\xf9D\xd6\xdc\xe3\x87\xa6\xbe\x01\xde\ +\xe3e\xe0O\x9eL\xf8\xf6\xf2`\x11\xe7\xd0\x11\x11\x11\ +Cq\x9a\xd9\xdd\xf3\x8dD\xd5\xdcd\xa2\xa9A\xf6-\ +/\x03\xff\xb0\xc3\x08\xe0^\xed\xd4\x89B\x89\x88\x88h\ +\xd07\xc4\x9af\x03zw\xa2*\xc7\x5c\x02\xb5\xb6\xf8\ +\x8e\x97\x09\xb0h\x11\xe1\xdb\x8b\x93&Q,\x11\x11\x11\ +\x0d\xba\xcel8\xff\x1d15\xb7\xb9\xc9\xd4`\xdb\xee\ +e\x02\xf4\xeaE\xf8\xf6\xe2\x9a5\x14KDDDC\ +&\xc5\xd6f\x03\xfa\x02\x22jns\x82\xa9\xc1v\xb4\ +\x97\x09PX\xa8R\x9b6\x11\xc0\xbd\xd8\xa8\x11E\x13\ +\x11\x11\xd1\x80?4\x1b\xce?\x11\xeb\x13Qs\x1b\xdd\ +\xfc>e\xd5e\xd1\xf1\xe3\x09\xdf^\x1c2\x84\xa2\x89\ +\x88\x88h\xc0af\x03\xfa\xcd\xc4S\xd0l15\xe8\ +N\xf72\x11\xf4\xcepe%\x01\xfcP\xce\x9bG\xd1\ +DDD\x0c\xd8\xfb\xcd\xb6V\xd4\x0e'\x9a\x82\xa6\xab\ +\xa9AWC|\xcd\xcb\x84\x98=\x9b\x00~\xa8v\x8b\ +;w*\xa7zu\x8a'\x22\x22b\x80\x9el6\x9c\ +\xbf\x97\xa0\xf79\xec\xc7s\xa6\x06\xdfj/\x13\xa2U\ ++B\xb8\x07\x93\xfa\x05V\x8a'\x22\x22b \xfeF\ +,4\x1b\xd0W\x12Ia\x7f\xce75\xf8\x8e\x10\xf7\ +x\x99\x18\x8b\x17\x13\xc2\x0f\xe5\x8c\x19\x14PDD\xc4\ +\x80\x9ci6\x9c\xffKlL$\x85\xfdi$~f\ +j\x10^\xe5\xa5\xa3\x8b\xde\x1d&\x84\x1f\xdc-[\x94\ +SXH\x11EDD\xcc\xb2/\x8a%f\x03\xfa\xf7\ +\x89\xa3p ~jj\x10v\xf729\x0a\x0a\x94s\ +\xd9e\x84\xf0C\x1ds\xe9\xd0\x81B\x8a\x88\x88\x98e\ +\x17\x9a\x0d\xe7\xda>DQ8\x10\xa3L\x0e\xc4;\xbc\ +L\x90\xc1\x83\x09\xe1\x87r\xf2d\x0a)\x22\x22b\x16\ +\xd5\x0d-j\x99\x0d\xe7O\x11C\xe1\x9b\xd0\xb7\x86\xdf\ +25\x18\x8f\xf70AR\xd5\xaa\xf1p\xd1\xa1\xba\xb9\ +\xac_\xaf\x9c\xbc<\x0a*\x22\x22btw\xcf\xa7\x12\ +C\xe1`\x5cdj0\x16\x88\x8fy9\x8b~\xdcq\ +\x04\xf1C\xd9\xae\x1d\x05\x15\x11\x111\x0b\xbe,\xd64\ +\x1b\xce\xff \x16\x13A\xe1`4H\xa4\x9f\x9852\ +(O\xf52Y\xd8E?\xf4.:\xc7\x5c\x10\x11\x11\ +\xb3\xe2|\xf3\xbb\xe7k\x89\x9f\xe0\x85\x1bM\x0d\xca\x22\ +\xf1I/\x13\xe6\xf8\xe3\x09\xe2\x07S\x7f\x81\xd1\x97j\ +)\xac\x88\x88\x88U\xea\xdcRj6\x9c\xebM\xd1&\ +DO\xf0B?\x93\xdf\x1c\xa7z\x994\xa5\xa5*\xb9\ +u+A\xfc`v\xecHqEDD\xac\x82s\xcd\ +\xef\x9e_M\xec\x04?<j\xdd.\xfa\xa8Q\x84\xf0\ +\x83\xb5[\x9c:\x95\xe2\x8a\x88\x88\x98\xa1O\xb8\x99\xc4\ +`8\xd7\xef\xcf\xb4$r\x82\x1fN5\xf9\x0dr\x86\ +\xd7\xb3\xe8\x1b7\x12\xc6\xbfI\xfd\x0bCQ\x11E\x16\ +\x11\x111\x03O5\xbf{~+q\x13\xfcR(\xee\ +65H\x8b\xc5\xe7\xbcL :\xba\x1c\xdc\xae])\ +\xb2\x88\x88\x88>\xbd\xdf\xed.g8\xa0\xf7 nB\ +&\x9cor\xa0N\xf62\x89\xf4\xb3\xf6k\xd6\x10\xc4\ +\xbf\xc9\xb3\xce\xa2\xd0\x22\x22\x22\xfa\xb4\xbf\xf9p\xfe\x0b\ +b&dJm\xf1C\x93g\xd1\x1f\xf72\x91\xfa\xf6\ +%\x88\x7fS\xbb\xc5\x8a\x0a\x95\xacY\x93b\x8b\x88\x88\ +\xe8\xd1[\xcd\x87s\xedq\xc4L\xa8\x0a;L\x0e\xd8\ +\x09^&\x93n'\xb8b\x05\x81\xfc\x9b\x1c<\x98\x82\ +\x8b\x88\x88\xe8\xc1\xa4\xd8\xd5|8\x7f\x8ax\x09U\xa5\ +\x95{\xcb\xd8\xc8\xa0\xcdw\xcf\x81\x1djB\xa5:u\ +\x22\x88\x7f\x93\x17_L\xd1EDD\xf4\xe0\x15\xe1\xec\ +\x9e\x9f@\xbc\x84lp\x83\xc9\x81;\xd2\xe3\xa4J\x9d\ +{.a\xfc\x9b<\xec0\x0a/\x22\x22\xe2A|K\ +lb>\x9c?I\xac\x84l\xd1A\xfc\xc2\xe4\x00\xbe\ +\xc3\xcb\xe4j\xdcx\xdf\x99k\x02\xf9\x01<\xf9d\x8a\ +/\x22\x22\xe2A<?\x9c\xdd\xf3Q\xc4J\xc8&\xdf\ +79\x80;\x89{\xbdL\xb0)S\x08\xe3\x07\xba,\ +\xbaaC\xfa\xac>\x05\x18\x11\x11\xf1k>\x9a0\xfe\ +(\x91\xf6A\xe2$d\x9b\x8e\xa6w\xd1\xb7{9\xe6\ +R\xbb\xb6r\xb6m#\x94\x1f\xe8e\xd1\xa3\x8e\xa2\x08\ +#\x22\x22\x1e\xc0\x11\xe1\xec\x9e\x0f%NB\x10\xdca\ +r \xebsao{\x99hC\x87\x12\xc8\x0f\xe4\x82\ +\x05\x14aDDD;\xda*>L\x8c\x84\xa08J\ +\xfc\xd2\xe4\x80>\xdf\xcbd\xcb\xcfOw.!\x94\x7f\ +\xd5\xcaJ\x95l\xd4\x88b\x8c\x88\x88\xb8\xdf\xc5\xd0\xc3\ +\xcd\x87\xf3/\xdc\x0c\x05\x10\x18w\x9b\x1c\xd45\xc4\xe7\ +\xbcL\xbaV\xad\xf6\x05R\x82\xf9\xff;\x8b>~<\ +\x05\x19\x11\x11\xd1\xf5\x82pv\xcfo#>B\xd0\xf4\ +0\xbd\x8b>\xc9\xeb\xc4\x9b:\x95P\xfe\xff\xdd\xb4I\ +%\x0b\x0b)\xca\x88\x88\x98\xf3>,V3\x1f\xce?\ +\x15\xdb\x12\x1f\xc1\x047\x99\xfe\xf6y\x9b\x97\xc9W\xab\ +\x96r\xb6l!\x94\xff\x7f\xbbw\xa70#\x22bN\ +\xab;\xc3u\x0fg\xf7|;\xb1\x11L\xd1\xd6\xfdF\ +hl\x80\xb7\x13w{\x99\x84\x83\x06\x11\xc8\xff\xbf\xe7\ +\x9dGqFD\xc4\x9cvc8\xe1\xfc\xcfb]b\ +#\x98\xe4;\xa6\x07\xfae^&a^\x9er\xe6\xcf\ +'\x94\xf3\xb2(\x22\x22\xe2>_\x10\xeb\x86\x13\xd0\x97\ +\x13\x17\xc14-\xc4\x7f\x99\x1c\xe8\xb5\xc4\xdfy\x99\x8c\ +\x8d\x1a\xa9\xd4\x8e\x1d\x84\xf2\xfd=\xe3\x0c\x8a4\x22\x22\ +\xe6\xa4'\x86\x13\xce\xf7\x8a\xa5\xc4E\x08\x83]\xa6\x07\ +\xfc)^'\xe4\x88\x11\x84\xf2\xfd\xbb\xb9\xe8/,\xa5\ +\xa5\x14jDD\xcc)\xaf\x0e'\x9ckO'&B\ +X4\x12?0=\xe8o\xf60!\x93\xba7\xfa\x92\ +%\x84\xf3\xfdC\xba\xfe\xd2B\xb1FD\xc4\x1c\xf1%\ +\xb1A8\xe1\xfc\x111\x8f\x98\x08a\xb2\xd8\xf4\xc0?\ +L|\xc3\xcb\xe4l\xde\x5c\xa5**\x08\xe7\xffv\xf5\ +\xea\xf4\x19}\x8a6\x22\x22\xe6\x80#\xc2\x09\xe7\xba\x89\ +\xc6\x91\xc4C\x08\x9b\xea\xe2{\xa6'\xc0\x5c\xaf\x13t\ +\xcc\x18\x82\xf9\xfe\xbb\xe8]\xbbR\xb4\x11\x111\xf6^\ +\x1f\xde\xd1\x96+\x89\x86`\x0b\x93MO\x80B\xf1^\ +\xafG].\xba\x88p\xee\x9a\x5c\xb8\x90\xc2\x8d\x88\x88\ +\xb1\xf6E\xb1Qxm\x15\xeb\x13\x0b\xc1\x16\xf49\xab\ +'MO\x84.\xe2\x1e/\x93\xb5qc\xe5\xd0\xd5\xe5\ +\xbf\xb6hA\x01GD\xc4\xd8:*\xbc\xdd\xf3yD\ +B\xb0\x8d\xfe\xe2\x97\xa6'\xc3R\xaf\x13v\xf8p\x82\ +\xf9\xbf\x8f\xb9\xcc\x9cI\x01GD\xc4X\xba-\xbcp\ +\xfe\x94X@\x1c\x04\x1b\xb9\xd9\xf4\x84(\x12\x7f\xe5\xf1\ +\xa8K\xea\xc2\x0b\x09\xe8\xda]\xbb\x94S\xa7\x0e\x85\x1c\ +\x11\x11c\xe5\x13bY8\xe1\xfcs\xb1;1\x10l\ +\xa5\x5c\xfc\xab\xe9\x89\xd1F|\xc7\xcb\xe4\xad[W9\ +\x9b7\x13\xd0\xb5\x13&P\xcc\x11\x1116\xee\x16\xbb\ +\x86\xb7{\xbe\x99\x08\x08\xb6\xb38\x8c\xc91\xdf\xeb$\ +>\xfah\xc2\xb9\xbe,\xbau\xabrJJ(\xea\x88\ +\x88\x18\x0b/\x0e/\x9c\xeb\x17Ck\x12\xff\xc0v\xf4\ +\xf9\xab\xdf\x9a\x9e \xf9\xe2\x8f=N\xe2}g\xb0\x09\ +\xe9\xca\x19:\x94\xa2\x8e\x88\x88\x91\xf7.\xb7\xbb[H\ +\x01\xfdx\xa2\x1fD\x85\xa1aL\x92\xd6\xe2\xdb^&\ +sq\xb1J\xad\x5c\xc9e\xd1\x0d\x1b\x94STDq\ +GD\xc4\xc8\xaa\x1f.l\x19^8\xff\x19\x91\x0f\xa2\ +\xc6\x0f\xc3\x98,g{\x9d\xd4\xadZ\xf1\xca\xa8>\xea\ +\xd2\xaf\x1f\x05\x1e\x11\x11#\xeb\xc4\xf0\xc2\xf9\x07b3\ +\xe2\x1eD\x8d\xa6\xe2\x87a\x1cu\xb9\xcd\xeb\xc4\x1e2\ +\x84\x80\xbev\xadr\x0a\x0b)\xf2\x88\x88\x189w\x86\ +\x17\xce\xb5g\x11\xf5 \xaa,\x0ac\xd24\x11_\xf1\ +:\xc1\xa7M\xe3,z\xdf\xbe\x14zDD\x8c\x94\x8f\ +\x8a\xa5\xe1\x85\xf3\xfb\x12\xe9G\x1a\x01\x22I\xa1\xf8L\ +\x18\x93g\xb4\xd7I^\x5c\xac\x9c\xe5\xcbs\xfb,\xfa\ +\xea\xd5\xfb\xfa\xc4S\xf0\x11\x111\x0a\xea\xfbfG\x86\ +\x17\xce\xff.\xb6$\xe2A\xd4\xe9 ~\x12\xc6$Z\ +\xefu\xb2\x97\x97+G\xb7\x1d\xcc\xe5]\xf4c\x8e\xa1\ +\xe8#\x22b$\x1c\x1b\xee\xd1\x96\xd9D;\x88\x0b\xeb\ +\xc2\x98D5\xc4\x87\xbdN\xf8\x1e=r;\xa0\xeb_\ +\x11\xf2\xf2(\xfc\x88\x88h\xb5\x97\x87\x1b\xce\x1f\x14\xf3\ +\x89u\x10\x17\xaa\x8b\xaf\x851\x99:xm\xbd\xa8\x9d\ +4)\xb7Cz\xb7n\x14\x7fDD\xb4\xd6{\xc5\xe2\ +p\x8f\xb6\xb4&\xd2A\xdc\x18(~\x11\xc6\xa4:\xd5\ +\xeb\xe4/(P\xce\xa2E\xb9\x1b\xd0\x97.e\x17\x1d\ +\x11\x11\xad\xf4U\xb1Y\xb8\xbb\xe7\xb3\x88r\x10W\xae\ +\x08kb\xed\xf4Z\x04\xea\xd6U\xa9M\x9br\xf7\xc2\ +h\xa7N,\x04\x88\x88h\x95Iqx\xb8\xe1\xfc\xa7\ +D8\x883e\xe2\xdba\x9dG\x7f\xd0k1h\xdf\ +^9\xb9\xfa\x88\xd1\xe2\xc5,\x06\x88\x88h\x95\x8b\xc3\ +\x0d\xe7\xbf\x17\x1b\x12\xe1 \xee\x0c\x0e\xeb\xa8K{?\ +\xe7\xd1\xc7\x8c\xc9\xdd]\xf46mX\x10\x10\x11\xd1\x0a\ +\xbf\x9bH?B\x18b@?\x91\xe8\x06\xb9\xc2\xce\xb0\ +&\xda\x04\xafE!/O%\xa7O\xcf\xcd\x90\xbe`\ +\x01\x8b\x02\x22\x22\x86\xeeCb\xcdp\xc3\xf9\xd5D6\ +\xc8%j\x88o\x845\xe1\xd6x-\x0e\xd5\xaa)\xe7\ +\xe2\x8bss\x17\xbdeK\x16\x07DD\x0c\xcd\xd7\xc4\ +\xd6\xe1\x86\xf3\xb7\xc4R\x22\x1b\xe4\x1a\xfd\xc3:\xeaR\ +$\xfe\xc4k\x91\xa8UK9\x97]\x96{!\xfd\x82\ +\x0bX \x10\x111\x14\xf7\x8a\xc7\x85\x1b\xce\xff%\xf6\ +$\xaaA\xae\xb2)\xac\xc9\xd7H|\xdek\xb18\xfc\ +p\xe5l\xdfNG\x17DDD\x03.\x087\x9ck\ +\x17\x13\xd1 \x97\xd1\xafq=\x10\xd6\x04\xec$\xbe\xe3\ +\xb5`\xe8G|*+s+\xa4/[F_tD\ +D4\xea\xc6\xf0\xc3\xf9O\xc4<\x22\x1a\xe4:\xfaU\ +\xae\x0f\xc3\x9a\x883|\x14\x8d\xd4\xc8\x91\xb9w\xd4\xa5\ +G\x0f\x16\x0cDD4\xa2>~Z-\xdcp.\xff\ +\x18\x89FD3\x804g\x86\xf9my\x87\x9f\x90~\ +\xc6\x19\xb9\x15\xd0W\xaeL\xbf\xb0\xca\xc2\x81\x88\x88\x01\ +\xfa\xb8X/\xdcp\xae\xef\xc5\x0d#\x92\x01|\x95\x9b\ +\xc2\x9a\x94\xfa\xdb\xfaO\xbd\x16\x11\x1dV\xcf??\xb7\ +B\xfa\x80\x01,\x1e\x88\x88\x18\x98\xaf\x84\xdf\xb1E\xbb\ +\x9e(\x06\xf0u\xea\x88\xef\x8551\xeb\x8bOz-\ +&\xa5\xa5*\xb5zu\xee\x5c\x16]\xbf^\xa5t\xcb\ +I\x16\x11DD\xcc\xb2\xbb\xc5\xfe\xe1\x87\xf3\x87\xc4B\ +\xa2\x18\xc0\x81\x19 ~\x1e\xd6\x04\xd5/\x8d\xbe\xee\xa3\ +\xb3Kr\xeb\xd6\xdc\xd9E\x1f:\x94\x85\x04\x11\x11\xb3\ +\xee\xa9\xe1\x87\xf3\x94\xd8\x84\x08\x06pp\x96\x879Q\ +\xfb\xb8\xdf\xe6=\x15\x966m\x94\xb3cGn\x04\xf4\ +\xcb/WN\x8d\x1a,&\x88\x88\x985\x17\x85\x1f\xce\ +u\xbf\xf3\xdeD/\x80CS \xfe:\xcc\x09;\xcb\ +\xcf\xa5\xd1\xae]U\xaa\xa2\x227B\xfa\x981,(\ +\x88\x88\x98\x15\xaf\x11\xf3\xc3\x0f\xe8\x17\x11\xbb\x00\xbc\xd3\ +P\xdc\x1b\xe6\xa4]\xe3\xa7\xd0\xe8K\x94\xb9\x10\xd0\xb7\ +oW\xc9\x9a5YX\x10\x11\xb1J\xde\x96H\xbf\xea\ +\x1dr8\xbf\x91\xb8\x05\xe0\x9f\xe3\x12\xe9\x96G\xa1L\ +\x5c]8n\xf1SpN8!7B\xfa)\xa7\xb0\ +\xb8 \x22b\xc6>\x95H\xbf\xe6\x1dr8\x7fS\xac\ +M\xd4\x02\xc8\x8c\xd5aN`\x99\xb9\xea\x11?\x85G\ +\x87\xd7\xb8\x07\xf4\x9d;\x95\xd3\xa0\x01\x8b\x0c\x22\x22\xfa\ +\xf65\xb1C\xf8\xe1\x5c?\x8e\xd8\x89\x88\x05P\xb5\xf3\ +\xe8\xf7\x879\x91[\xba\xfdY\xbd\x14\x9ed~\xber\ +\xe6\xce\x8d\x7fH\x9f:\x95\x85\x06\x11\x11}\xf9\x8e\xd8\ +;\xfcp\xfe\xa58\x9ex\x05Pu\x1a$B\xec\x8f\ +\xae\xed'\xbe\xeb\xb5\x08\x15\x16*g\xfe\xfcx\x07\xf4\ +\xcaJ\xe5\xb4j\xc5\x82\x83\x88\x88\x9e\xdc#\x0e\x0f?\ +\x9c+\xf7\x97y\x00\xc8\x12=\xc4\x8f\xc3\x9c\xd4'\x88\ +\xef{-F\xd5\xab+\xe7\xe2\x8b\xe3\x1d\xd2\x17/V\ +N^\x1e\x0b\x0f\x22\x22\x1e\xfc\xd7eq\x92\x1d\xe1\xfc\ +\x0e1\x9fH\x05\x90]&\x87=\xb9Ov\x0b\x8d\xa7\ +\xa2T\xbb\xb6r\xd6\xac\x89uHOv\xef\xce\xe2\x83\ +\x88\x88\x07u\x9a\x1d\xe1\xfc\x05\xb1\x8c(\x05\x10\x0cW\ +\x85=\xc9\x17\xf9\xe9\x91\xde\xa4\x89Jm\xda\x14\xdf\x90\ +\xbejU\xfaH\x0f\x0b\x10\x22\x22\x1e\xc0\xe5v\x84\xf3\ +\xbf\x88\xed\x89P\x00\xc1Q(>\x14\xf6d_\xe5\xa7\ +@\x95\x97\xab\xd4\xc6\x8d\xf1\x0d\xe9#F\xb0\x08!\x22\ +\xe2\xd7\x5ccG8\xd7\xc7c\xfb\x13\x9f\x00\x82\xe7p\ +\xf1\x0faN\xf8\x02\xf1:?\x85\xea\xb0\xc3\x94\xb3y\ +s<\x8f\xb9l\xdd\xaa\x9cZ\xb5X\x8c\x10\x11\xf1?\ +^/\x16\xda\x11\xd0g\x10\x9b\x00\xcc1D\xfcW\x98\ +\x93\xbeX\xfc\x89\x9f\x82u\xc4\x11\xca\xb9\xfc\xf2x\xee\ +\xa2O\x9e\xcc\x82\x84\x88\x88\xfb\xfc\xb1\xbbFZ\x10\xce\ +7\x10\x97\x00\xcc3)\x91\xeeg\x1a\xda\xe4/\x13\xef\ +\xf5S\xb8Z\xb6T\xce\xb6m\xf1\x0b\xe8\x15\x15\xcai\ +\xda\x94\x85\x09\x111\xc7\xbdS,\xb1#\x9c\x7fO\xcc\ +#*\x01\x84\xc3\xba\xb0\x8b@}\xf1Q?\x05\xac}\ +{\x95\xda\xb1#~!}\xc1\x02\x16'D\xc4\x1c\xf6\ +!\xb1\xae\x1d\xe1\xfc\xd7b5\x22\x12@x\xe8\x97F\ +\xef\x0c\xbb\x18\xb4\x11_\xf6S\xc8:vT\xa9\x9d;\ +\xe3\x17\xd2;wf\x91BD\xccA\x9f\x15\x9b\xd9\x11\ +\xce\xdf\x13\x1b\x13\x8f\x00\xc2\xa7D\xfcM\xd8E\xa1\xab\ +\xf8\x86\x9f\x82\xd6\xad\x9brv\xed\x8aU@O\xadX\ +\xa1\x9c\x82\x02\x16+D\xc4\x1cR\x16`u\x18\xed\x14\ +\x01\xe0\x004\x17\x7f\x1fvq8.\x91~\xce\xd8s\ +a;\xfah\x95\xd2\xe7\xb7\xe3\xb4\x8b>x0\x0b\x16\ +\x22b\x8e\xf8\x82\xd8\xd6\x8ep\xfe\x998\x8a8\x04`\ +\x1fG\x8b\xff\x08\xbbH\x8c\xf2\x19\xd2S\x03\x07*\xa7\ +\xb22>\x01]\xf7|/)a\xe1BD\x8c\xb9\xcf\ +\x8b\xad\xec\x08\xe7\xb4S\x04\xb0\x9c\x09\xe2\x17a\x17\x8a\ +\x13\xc5\xf7\xfd\x14\xbac\x8eIwB\x89\xcbQ\x97\xd3\ +Nc\xf1BD\x8c\xb1/\x89\x1d\xed\x09\xe7\xb4S\x04\ +\x88\x00\xcbm(\x18\xa7\x8a{\xfd\x14\xbc\x1e=\xe2s\ +\xdcE\xff\x22\xd0\xa2\x05\x8b\x18\x22b\x0c}E<\xd2\ +\x9ep\xfe\xc3\x04\xed\x14\x01\x22\x81\x9e\xa8\xb7\xdaP8\ +\xe6\xf9-|q\x0a\xe9K\x96('/\x8f\xc5\x0c\x11\ +1F\xbe)\xf6\xb4'\x9c?%\x96\x11{\x00\xa2C\ +u\xf1q\x1b\x0a\xc8\x1c\x9f\xc5/\xd9\xbd{|B\xfa\ +\x80\x01,h\x88\x881Qw*\xebaO8\x7f^\ +\xacM\xdc\x01\x88\x1eM\xc5wm($\xcb\xfd\x16\xc2\ +\xa3\x8f\x8eG\x0b\xc6\xcd\x9bU\xb2\xac\x8c\x85\x0d\x111\ +\xe2\xcab\xaa\x06\xd9\x13\xce\xdf\x17\x9b\x11s\x00\xa2K\ ++1eCA\xb9\xc4\xefN\xfaQG\xc5#\xa4\x9f\ +q\x06\x8b\x1b\x22b\x84}G\x1chO8\xd7kz\ +k\xe2\x0d@\xf4\xe9\x22\xfe5\xec\xa2\x92'\xae\xf7[\ +\x18;w\x8e\xfe\x8b\xa3\xfa\xc2h\xcb\x96,r\x88\x88\ +\x11\xdd9\x1flO8\xd7kyWb\x0d@|8\ +^\xfc4\xec\xe2R ^\xe1\xb7@v\xea\xa4\x9c\x1d\ +;\xa2\x1d\xd2\x97.UN~>\x8b\x1d\x22b\x84\xd4\ +oz\x8c\xb5'\x9c\xffK\x1cA\x9c\x01\x88\x1f\xa7&\ +,\xe8\x91\x9e\x9fAHO\xc5!\xa4\xf3\xc2(\x22b\ +\xa4v\xce\x8f\xb5'\x9c\xebWB\xc7\x12c\x00\xe2\xcb\ +E6\x14\x9b\x22\xf1\x1a\xbf!\xbdk\xd7h\x1fw\xd9\ +\xbcY9\x5c\x18ED\xb4\xde\xdd\x89\xf4\xab\xd8\x09{\ +<\x87\xf8\x02\x10\x7f6\xd8Pp\xf4q\x97\xed~C\ +z\x9b6\xca\xd9\xb2%\xba!\xfd\xcc3Y\xfc\x10\x11\ +-\xefs\xde\xd7\xaep\xbe\x94\xd8\x02\x90\x1b\xe8\x87\x8c\ +\xae\xb5\xa1\xf0\xe8\x8b\xa3\x1b\xfc\x16\xd0#\x8eP\xa9M\ +\x9b\xa2{a\xb4m[\x16ADDK\xc3y\x1f\xbb\ +\xc2\xf9\x16\x22\x0b@nQ \xdenKH\xf7\xdd\xdd\ +\xa5qc\xe5\xac[\x17\xcd\x90\xbe|\xb9r\x0a\x0aX\ +\x0c\x11\x11-{\x84\xa8\x97]\xe1\xfc:wC\x0d\x00\ +r\x8c\x9a\xe236\x14\xa2\xfc\x0c\x8e\xbb8\xe5\xe5\xd1\ +\x0d\xe9C\x87\xb2 \x22\x22Z\xe2[b\x7f\xbb\xc2\xf9\ +\xbdb5b\x0a@\xeeR_|\xc5\x96\x9d\xf4\xb5~\ +\xcf\xa4\xd7\xae\xad\x92\x97\x5c\x12\xb9\x80\x9e\xd2\x1di\x1a\ +6daDD\x0cYY\x00UW\xbb\xc2\xf9\xcf\x09\ +\xe7\x00\xa0\xd1\xaf\x8d:\xb6\x84\xf4M~\x0bli\xa9\ +r.\xbc0z\xbb\xe8\xe7\x9f\xaf\x9c\xbc<\x16HD\ +\xc4\x90|]\xeciW8\x7fL,#\x96\x00\xc0\xbf\ +i#&m)RK\xfd\x16\xda\x92\x12\xe5,Z\x14\ +\xbd\x9d\xf4>}X$\x11\x11C\xf0%\xb1\x93]\xe1\ +\xfc!\xb1\x06q\x04\x00\xfe?G\x89\x7f\x89\xecq\x97\ +j\xd5\x94s\xee\xb9\xd1\xeb\x8d^\xb3&\x8b%\x22\xa2\ +A_\x15\xbb\xd9\x15\xce\x9f\x17\xeb\x12C\x00\xe0\x9b\xe8\ +%~`KH_\x95IH\x9f7/R!=9\ +u*\x0b&\x22\xa2\xc1\x9ds\xcb\xce\x9c\xbf(6 \ +~\x00\xc0\xa1\x18(~dK\xf1Z\xee\xb7\x00\xe7\xe7\ ++\xe7\xf4\xd3\xa3\xb5\x93\xde\xa5\x0b\x0b'\x22b\xc0>\ +/\xb6\xb3+\x9c\xbf*\x96\x13;\x00\xc0+\xfd\xc4\xbf\ +\xdbR\xc4f\x88I?\x85X_\xbe\x1c=::\xbb\ +\xe8k\xd7*\xa7\xb8\x98\x05\x14\x111 \x1f\x11\x0f\xb3\ ++\x9c\xbf$6$n\x00\x80_\x8e\x13?\xb6\xa5\x98\ +M\x11\xf7\xfa-\xcaC\x86\xa4_\xef\x8cBP?\xf9\ +d\x16QD\xc4\x00\xfc\x95\xd8\xc0\xaep\xfe\x0a;\xe7\ +\x00P\x15F\x89\x9f\xd8R\xd4N\x12w\xfb-\xce\xbd\ +z)g\xd7.\xfb\x03\xba\xfe\x22\xd1\xb2%\x8b)\x22\ +b\x16\xbdS\xaceW8\x7f[<\x9cx\x01\x00U\ +e\x82\xf8\x99-\xc5m\xb8\xf8\xae\xdf\x22\xdd\xb9\xb3r\ +\xb6o\xb7?\xa4\xebG\x97\x0a\x0aXT\x11\x11\xb3\xe0\ +Mb\x0d\xbb\xc2\xb9,_\x89f\xc4\x0a\x00\xc8\x16s\ +\xc4/m)r#\xc4\xf7\xfc\x16\xeb\x16-\xd2m\x0d\ +m\x0f\xe9#F\xb0\xb0\x22\x22V\xd1\x1f\x88%v\x85\ +\xf3?\x88\x1d\x89\x13\x00\x90m\xce\xb3\xa8\xd0\xa9\x81\xe2\ +[~\x8bv\x93&\xcaY\xb7\xce\xee\xc7\x8bv\xeeT\ +Ny9\x0b,\x22b\x86^#\x16\xd9\x15\xce\xffW\ +\xecN\x8c\x00\x80\xa0\xb8\xd8\xa6\x90\xae\x9fh~\xcdg\ +\xe1N6j\xa4\x9c5k\xec\xdeE\xd7\x0f.\xe9N\ +4,\xb4\x88\x88\xbe\xdc.\x16\xd8\x15\xce\xff(v#\ +>\x00@\xd0\x5chSH\xef\xe2><\xe1\xebA\xa3\ +:uTR\x9f\xf7\xb6\xb9\xf5b\xbf~,\xb6\x88\x88\ +>\xd4/P\xe7\xd9\x15\xce\x7f/v&6\x00\x80)\ +\x16&,:\x93\xde\xce}\x80\xc2W1/.V\xa9\ +s\xce\xb17\xa4o\xdf\xae\x92\x0d\x1a\xb0\xe8\x22\x22z\ +\xf0B\xbb\x82\xb9V\xfe\xb18s\x0e\x00\xe6\x99%~\ +aK1\xd4\x0fP<\xe6\xb7\xa8\x17\x16\xaa\xe4\xf4\xe9\ +\xf6\x86\xf4\xf3\xce\xe3\xa8\x0b\x22\xe2A\xdc#\x9ej_\ +8\xd7\xad\x14\x9b\x13\x13\x00 ,\xe6\xd9\xb4\x93\xdeD\ +|\xd8o\x81\xd7\x01\xf8\xa4\x93\xec\xbd4:p \x8b\ +0\x22\xe2\x01\xd4\xefb\x9cl_8\x97\xef\x0c\x896\ +\xc4\x03\x00\x08\x9b\xc9\x09\x8b\xfa\xa4\xeb\x07)~\x92I\ +\xb1\x1f:\xd4\xceWGu\xffv\x8e\xba \x22~\xc5\ +\xd7\xc5\xfe\xf6\x85\xf37\xc5#\x88\x05\x00`\x0b\xa7\xda\ +\x14\xd2\xab\x89\xd7fR\xf4{\xf6T\x8ensh[\ +H_\xb0\x80\xa3.\x88\x88\xae/\x8a\xdd\xec\x0b\xe7/\ +\x8b\x8d\x89\x03\x00`\x1b\x93l\x0a\xe9\xba\xcd\xd6\xd6L\ +\x8a\x7f\xfb\xf6\xca\xd9\xba\xd5\xbe\x90\xde\xbf?\x0b3\x22\ +\xe6\xbcO\x8bm\xec\x0b\xe7\xf2\x9d!QN\x0c\x00\x00\ +[\x99(~jK\xd1\xd4\xed\xb6\x96g\xb2\x084m\ +j\xdf\x83F\xf2\xa5!U\xaf\x1e\x0b4\x22\xe6\xac\xf7\ +\x8b\xe5\xf6\x85\xf3\x17\xc4F,\xff\x00`;'\xdb\x14\ +\xd2\xb5\xb3\xf4\x03E~\x17\x83\xfa\xf5\x95\xb3b\x05G\ +]\x10\x11-\xf0.\xb1\x8e}\xe1\xfc\xb7bC\x96}\ +\x00\x88\x0aV\x9dI\xd7N\x17\xf7\xfa]\x14JK\x95\ +\xb3h\x91]!\x9d\x07\x8c\x101\xc7\xbc\xddm\x00`\ +Y8\x7fZl\xc0r\x0f\x00\x1cw\xa9\xa2c\xdd\xb6\ +\x5c\xbe\x16\x87\x92\x92\xf4\xce\xb5-\x01}\xf3f\x95\xaa\ +]\x9bE\x1b\x11s\xc2\x1b\xc4\xea\xf6\x85\xf3\x87\xc5Z\ +,\xf3\x00\x10UN\x12?\xb1\xa9\xb0\x0e\x12\xdf\xf4\xbb\ +H\xe4\xe7\xab\xd4i\xa7\xd9\x13\xd2\xe7\xcf\xe7\xa8\x0b\x22\ +\xc6\xde\x1db\xa1}\xe1\xfc\x1e\xb1\x06\xcb;\x00D\x9d\ +\xe1\xe2?l*\xb0G\x89/e\xf2\xa0\xd1\x981\xf6\ +\x84\xf4^\xbdX\xc0\x111\xb6\xaer/\xfa[\x16\xce\ +o\x17\x8bY\xd6\x01 .\xf4\x17\xffjS\xa1m\xe3\ +\xb6\xeb\xf2\xbdp\xe8`lC\xaft\xfd\x80Q\xc3\x86\ +,\xe4\x88\x18+\xf5\x85\xfey\xf6\x05s\xed\x8db!\ +\xcb9\x00\xc4\x8d\xa3\xc5?\xdaTp\x1b\x8a\xf7f\xda\ ++}\xcb\x96\xf0C\xba\xbe\xc0\x9a\x9f\xcf\xa2\x8e\x88\xb1\ +P\xdf\x11\x9ahg8\xff\xb6\x98\xcf2\x0e\x00q\xa5\ +\xa5\xf8\x96M\x85\xb7\xc4\xbd\x84\xe4{1i\xd2D%\ +\xd7\xae\x0d?\xa4\x8f\x18\xc1\xc2\x8e\x88\x91\xf75\xb1\x9f\ +\x9d\xe1|\x09K7\x00\xe4\x02M\x12\xe9W\xd7\xac)\ +\xc0\xfa\xd5\xd1M\x19,(\xfb\xba\xa9,]\x1an@\ +\xdf\xb5K9\xcd\x9b\xb3\xc0#bd}Flo_\ +0\xffR<\x97%\x1b\x00r\x09\xfd\xea\xda\xf3\xb6\xed\ +\x94\x9c\x93\xc9\xe2R\x5c\xac\x9cy\xf3B\x0d\xe9\xa9K\ +/UNQ\x11\x0b=\x22F\xce\x87\xc5\xc3\xed\x0b\xe7\ +_\x88sX\xaa\x01 \x17\xa9#>j[H?U\ +\xdc\xe3\xf7R\x93>\x07>yr\xb8;\xe9\x13'\xb2\ +\xd8#b\xa4\xfc\xa9X\xdb\xbep\xae\xdf\xef\x98\xcc\x12\ +\x0d\x00\xb9\x8c\xee%{\xafm!}\x84\xf8v&m\ +\x18G\x8fVNee8\x01]\xff\xe7\x1ey$\x8b\ +>\x22F\xc2k\xc4j\xf6\x85\xf3\x8f\xc5\x13Y\x9a\x01\ +\x00\xd2!\xfdn\xdbBz\x7f\xf7\xd2\x92\xef\x85\xa7O\ +\x9f\xf4\xb9\xf00B\xfa\xbau\xca)-e\xf1GD\ +\xab\xdd%\x16\xd9\x17\xce?\x12G\xb3$\x03\x00\xfc\x97\ +j\xe2\x8fl\x0b\xe9\x1d\xc5\xe73Y\x80:tP\xce\ +\xd6\xad\xe1\x84\xf4\x193\x08\x00\x88h\xad\xcb\xed|\x80\ +\xe8/b?\x96b\x00\x80\x03\x87\xf4\x9bm\x0b\xe9\xfa\ +\xf2\xd2C\x99,DM\x9b\xa6w\xb4\xc3\x08\xe9\xc7\x1c\ +C\x10@D\xab\xdc+~\xcb\xce6\x8a\xf2\x8f\x96\xe8\ +\xcc\x12\x0c\x00\xf0\xcd\xe8\x87 \xae\xb0\xad\x80\xd7\x15\xef\ +\xcc\xa4\x0dc\x9d:\xcaY\xb6\xcc|@\xdf\xb2E\xa5\ +\xea\xd5#\x14 \xa2\x15\xbe+\x8e\xb13\x9c\xbf&6\ +g\xe9\x05\x00\xf0\xc6J\xdb\x0ayu\xf1\xbb\x99,N\ +%%\xca9\xff|\xf3!}\xc1\x82\xf4\xc5U\xc2\x01\ +\x22\x86\xe8\xabbo;\xc3\xf9\xd3bC\x96[\x00\x00\ +\x7fL\x15?\xb3\xa9\xa0\xebs\x93\x8b2Y\xa4t\x8f\ +\xf2\xd9\xb3\xcd\xf7G\x1f<\x98\x80\x80\x88\xa1\xf9\xa8\xd8\ +\xdc\xcep\xfe\xb3D\xbaA\x01\x00\x00d\xc0\x18\xf1\x9f\ +\xb6\x15\xf7Y\xeey\xca\x8c\xda0\x9a\x0c\xe8;w*\ +\xe7\x88#\x08\x0a\x88h\xdc;\xdd\xe3\x81\x16\x86\xf3k\ +\xc5\x02\x96W\x00\x80\xaa1H\xfc\x9bmE~T&\ +\xbd\xd2\xb5}\xfb\xaaTE\x85\xd1WFS\xd5\xaa\x11\ +\x18\x10\xd1\x987\x885\xec\x0c\xe7\x9b\xc4<\x96U\x00\ +\x80\xec\xd0)\x91\xbeioU\xb1\xef.\xbe\x90\xc9\x02\ +\xd6\xb1\xa3J\x1al\xc3\x98\xd2\xaf\x9c\x12\x1a\x10\xd1\x80\ +\x92\x80U\x81}\xc1\xfcK\xf1<\x96R\x00\x80\xec\xd3\ +R|\xc3\xb6\x90\xde\xdc=g\xe9{!k\xd5J9\ +\x9b7\x9b{e\xb4S'\xc2\x03\x22\x06\xea9v\xee\ +\x9a\xeb\xbbLg\xb2\x84\x02\x00\x04G\xb9\xf8\x9cm\x0b\ +\x80>gyG&\x0bZ\xfd\xfa\xcaY\xb1\xc2LH\ +\xbf\xfcrZ/\x22b \xee\x16O\xb53\x9c\xeb;\ +LcX:\x01\x00\x82\xa7\x9e\xf8\x84m\x0bA\x99\xf8\ +\x83L\x16\xb7\xd2R\xe5\x5cp\x81\x99\x90\xae\xdb=\xe6\ +\xe7\x13(\x101\xab=\xceO\xb07\x9c\x9f\xc8\x92\x09\ +\x00`\x8e\xd2D\xbaM\x96U\x0bB\xa1\xb85\x83\x05\ +.YX\xa8\x9cY\xb3\xcc\x84\xf4\xe1\xc3\x09\x15\x88\x98\ +\x15_\x11{\xd9\x19\xce\xff,\xf6c\xa9\x04\x000\x8f\ +n\x93u\xb5\x85\x0b\x83Z\xa8C\xb7\xdf\xc5.?_\ +%'M\x0a>\xa0\xef\xda\xa5\x9c\x16-\x08\x17\x88X\ +%\x9f\x12\xdb\xda\x19\xcew\x8b\x1dY\x22\x01\x00\xc2\xc5\ +\xbaWG\xb5\x93\xdcs\x99\xbe\x17\xbe\xa1C\xd3\x97:\ +\x83\xec\xea\xb2z\xb5JU\xafN\xc8@\xc4\x8c\xfc\x95\ +Xng8\x7fA<\x8ce\x11\x00\xc0\x0e\xa6\x88\x9f\ +\xda\xb6X\xf4\x10_\xcad\x01<\xfah\xe5\xec\xd8\x11\ +\xecN\xfa\x94)\x04\x0dD\x8cS\x8f\xf3_$\xd2\xc7\ +\x1f\x01\x00\xc0\x22\x86\x89\x1f\xd8\xb6h\xb4\x10\x1f\xcfd\ +!l\xdf^9[\xb6\x04\x1b\xd2{\xf4 p \xa2\ +g7\xda\xd9\xe3\xfc\xdf\xaf\x83\x16\xb2\x0c\x02\x00\xd8I\ +\x97\x84\x85\x0f\x1a5\x12\xef\xc9\xe4\xf2h\xb3f*\xb5\ +qcp\x01}\xd3&\xe5\xd4\xaeM\xf0@\xc4\x83\xd7\ +\x22{{\x9ckW%x\x1d\x14\x00\xc0z\xf4\x83F\ +\xaf\xd9\xb6\x88\xd4p\x7f\x1a\xf6\xbd8\xea\x00\xbdlY\ +p\xe7\xd1/\xbcP9\x05\x05\x84\x10D\x8cZ\x8f\xf3\ +/\xc4\x05,y\x00\x00\xd1A\xf7J\x7f\xcc\xb6\x05E\ +\xff4\xbc!\x93E\xb2\xa4$\xdd\xc3<\xa8\x9d\xf4\xb1\ +c\x09\x22\x88\xf85\xdf\x10\x07\xd9\x19\xce?\x16'\xb0\ +\xd4\x01\x00D\x0f+{\xa5kg\x89{\xfd.\x96\x85\ +\x85*9}z0\x01]w\x8d\xe9\xd8\x91@\x82\x88\ +\xff\xf1wb7;\xc3\xf9\xdf\xc4\xa1,q\x00\x00\xd1\ +E\xf7J\xbf\xc6\xc6\x90>\xc6}\x81\xcf\xd7\xa2\x99\x97\ +\xa7\x9c\xd1\xa3\x83\x09\xe9\xfa\xac;\xe7\xd1\x11Q|D\ +lfg8\x7f_\xec\xcc\xd2\x06\x00\x10}\xf2\xc5m\ +6\x86\xf4c\xc573Y@\x87\x0c\x09\xa6W\xba>\ +F\x93\x9fO@A\xcca\x7fio\x8f\xf3w\xc4\xf6\ +,i\x00\x00\xf1bQ\x22}\xa9\xc8\xaaE\xa7\x8b\xf8\ +|&\x0bi\xb7n*\x15D\xaf\xf4\xe3\x8f'\xa4 \ +\xe6\xa87\x8bev\x86\xf3g\xc5\xc6,c\x00\x00\xf1\ +d\xac\xf8\x91m\x8bO\xb9\xbbk\xe5w1M\xb5l\ +\x99n\x95\x98\xed\xf3\xe8\xba\x07;a\x05\x91\x1e\xe7v\ +x\xa7X\x83\xe5\x0b\x00 \xde\x0c\x14\xffl\xdb\x22T\ +[\xbc=\x93\x85\xb5aC\xe5\xacZ\x95\xdd\x90\xben\ +\x9dr\xca\xca\x08-\x889\xe2r1\xcf\xcep\xfe]\ +\xb1\x88e\x0b\x00 7\xe8\x90H\x9fg\xb4j1\xaa\ +&^\x9b\xc9\x02[\xab\x96r\x96.\xcdnH\x9f7\ +/})\x95\xf0\x82\x18\xeb\x07\x88\xe6\xda\xfb\x00\xd1\xba\ +\x04\x0f\x10\x01\x00\xe4\x1c\xbaW\xfa\xc3\xb6-Jz\x17\ +\xeb\x92L\x16\xdb\xe2\xe2t\xa8\xcefH\x1f6\x8c\x10\ +\x83\x18S\xdf\x11G\xd9\x19\xcc?\x15\xcfd\x89\x02\x00\ +\xc8]\x8a\xc5\x9bl\xdc=\xca\xa4WzRw`9\ +\xfd\xf4\xec\x05\xf4]\xbb\x94\xa3\xcf\xb9\x13f\x10c\xe5\ +Kb\x0f;\xc3\xf9\x07\xe2q,M\x00\x00\xa0\x7fB\ +\xddhcH?\xde\xdd\xe5\xf2\xdd+}\xc2\x84\xec\x85\ +\xf4\x95+U\xaazuB\x0dbL|Zlgg\ +8\xdf+veI\x02\x00\x80\xfd9/aa\x1bF\ +\xbd\xcb\xf5b&\x0b\xf1q\xc7e\xafW\xfa\xcc\x99\x04\ +\x1b\xc4\x18x\x9f\xbd=\xce_\x15[\xb2\x0c\x01\x00\xc0\ +\x81\x18/\xfe\xd3\xb6\xc5\xab\x85\xf8X\x86\xbd\xd2\x9dl\ +\xf5J\xe7<:b\xa4\xd5]\xa2j\xd9\x19\xce\x1fI\ +\xa4\xef\x04\x01\x00\x00|#}\xc4?\xda\xb6\x885\x14\ +\xef\xcedan\xdbV9[\xb6T9\xa0\xa7**\ +\x94\xd3\xba5A\x071\x82^\xe5v\x89\xb20\x9c\xdf\ +\x9aH\xdf\x05\x02\x00\x008$\xad\xc5\xd7m[\xccj\ +\x887d\xf2\xa0Q\xd3\xa6\xe9\xde\xe6Y\xe8\x8f\x9e\xa4\ +?:b\xa4\x5cg\xef\x03DW\x88\x05,7\x00\x00\ +\xe0\x87\xfa\xe2\xa3\xb6-jz\xa1\xdd\x90\xc9B]\xbf\ +\xberV\xac\xa8zH_\xb0@9\xba[\x0c\xc1\x07\ +\xd1\xfa\x1e\xe7\xb3\xec\x0c\xe6_&\xd2w~\x00\x00\x00\ +2\xa2\xa6x\xafm\x0b\x9c\xee\x95\xbe$\x93E\xbb\xb4\ +T9\x8b\x16U=\xa4\x9fp\x02\x01\x08\xd1b\xdf\x17\ +\xcf\xb43\x9c\x7f.\x9e\xc5\xd2\x02\x00\x00UE?3\ +}\xbd\x85\x0b\x9d\x9a\x22\xee\xf1\xbbxW\xabV\xf5\x07\ +\x8dtw\x98\x8e\x1d\x09B\x88<@\xe4\xc7\x8f\xc4\xb1\ +,)\x00\x00\x90M\xacl\xc38@|-\x93\x07\x8d\ +\xce8\xa3j\x97F7mRN\x9d:\x04\x22D\x8b\ +|A\xecfo\x8f\xf3.,#\x00\x00\x10\x04'\x8b\ +\x1f\xdb\xb6\xf8u\x10\x9f\xc9\xe4A\xa3\xd1\xa3\xab\xb6\x93\ +\xbex\xb1r\x0a\x0b\x09F\x88\x16\xa8[\xb16\xb7\xb7\ +\xc7y\x0b\x96\x0f\x00\x00\x08\x92~\xe2\x9fl[\x04\xf5\ +\xe3#\xbf\xcada\x1f5\xaaj\x0f\x1a\x8d\x1dK8\ +B\x0c\xd9{\xdcV\xac\x16\x86sz\x9c\x03\x00\x801\ +\x8e\x14\xdf\xb3m1,\x13\x7f\x98\xc9\x02\xdf\xb3\xa7r\ +v\xed\xca\xfc<\xfaQG\x11\x92\x10C\xf2\xfbn\x0b\ +V\x0b\xc39=\xce\x01\x00\xc08\x8d\xc5gl[\x14\ +\x8b\xc4\x8aL\x16\xfa\xa3\x8fV\xa9\x9d;3\x0b\xe9\x9b\ +7+\xa7^=\xc2\x12\xa2a\xb7\x8a\x85v\x86\xf3\xca\ +\x04=\xce\x01\x00 $J\xc5\x9f\xd9\xb68\xea6\x8c\ +\x8b2y\xd0\xa8M\x9b\xcc_\x1d]\xb6L\xa5t\x87\ +\x18B\x13\xa2\x11\x17\xb9s\xdd\xb2\xfa\xa3/\xd2\xd3\xe3\ +\x1c\x00\x00BG\xef\x12}\xdb\xc2\x1d,59\x836\ +\x8c\xfa\xd5\xd1\xd4\xfa\xf5\x99\x85\xf4\xe9\xd3\x09N\x88\x01\ +\xbbW\x9ci\xe7\xae\xf9\xa7\xe2T\x96\x04\x00\x00\xb0\x85\ +<q\x9d\x8d!}\x8c\xf8n&\xaf\x8e\xaeZ\x95Y\ +H\x1f0\x80\x10\x85\x18\x90\xbb\xc5\x89v\x86\xf3\x0f\xc5\ +\x13X\x0a\x00\x00\xc0F\xceN\xa4_\xca\xb3j\xf1\xec\ +%\xbe\xe27\x0c\xd4\xaa\xb5\xef\xd8\x8a\xef\xfe\xe8\xfa\x1c\ +{\xf3\xe6\x84)\xc4,\xfb\xa68\xd8\xcep\xfe{\xb1\ +\x07\xe5\x1f\x00\x00l\xe68\xf1\x03\xdb\x16\xd1f\xe2#\ +~CAI\x89r.\xb8\xc0wHO\xae]\xab\x9c\ +\xb22B\x15b\x96\xd4\xef\x1c\xb4\xb73\x9c\xffNl\ +J\xd9\x07\x00\x80(\xa0_\xcc\xdbk\xdbbZG\xfc\ +\xa9\xdf3\xe9\xfa\xe2\xe7\xbcy\xfe\x8f\xba,X\xa0\x1c\ +\xfdb)\xe1\x0a\xb1J\xde\xef\xbes`a8\xd7=\ +\xce\xebR\xee\x01\x00 J\xb4\x15\xdf\xb2mQ-u\ +\xfb&\xfb\x09\x08I\x1d\xb4\xa7N\xf5\x1f\xd2\xf5K\xa5\ +\x04,\xc4\x8c\xbdWl`g8\xbfG,\xa3\xcc\x03\ +\x00@\x14i$>e\xdb\xe2\xaa\xfb&_\xe17,\ +\xe4\xe5)g\xc2\x04\xff\x8f\x18u\xeaD\xd0B\xcc\xc0\ +\x1f\x8b\xb5\xec\x0c\xe7\xdf\x13\x8b(\xef\x00\x00\x10e\xf4\ +Kz7\xd9\xb6\xc8f\xd4+]\x87\xf4\xf1\xe3\xfd]\ +\x1a\xdd\xb4I9u\xeb\x12\xb8\x10}\xf8m\xf7\xd11\ +\x0b\xc3\xf9\x12J:\x00\x00\xc4\x05\xdd\x86q\x93\x85\x8b\ +\xad\x9a\xe1\xf6U\xf6\x15 \x86\x0f\xe7\x11#\xc4\x80\x5c\ +i\xe7\x03D\x9f\x893(\xe5\x00\x00\x10G\xf4\x0b{\ +_\xd8\x16\xd2\x8f\xcf\xa0Wzj\xe0\xc0\xf4\x11\x16\xaf\ +!}\xda4\xc2\x17\xe2!<\xc7\xce]\xf3\x7f\x8ac\ +)\xdf\x00\x00\x10g&\xb8\x0b\x9eU\x8bp?\xf15\ +\xbf\x81b\xd0 \x7f!\xbdwoB\x18\xe27\xbc\x0e\ +:\xcd\xcep\xfe'\xb17e\x1b\x00\x00r\x81\xbe\xee\ +\xc2g\xd5b\xdcA|\xceo\xb8\xe8\xd1C9\xbbv\ +y\x0b\xe8\xf2\xff/\xd5\xa6\x0d\x81\x0cq?\xf5\xafW\ +\xa3\xec\x0c\xe7\xbb\xc5\x8e\x94k\x00\x00\xc8%\x8e\x14\xdf\ +\xb3mQ>B|\xd4o\xc8\xe8\xdcY9;vx\ +\xbb4\xbaa\x83J\xd5\xa9C0C\x14_\x17\xfb\xdb\ +\x19\xce\x9f\x17\x9bP\xa6\x01\x00 \x17\xd1\x0b\xe0\xb3\xb6\ +-\xceu\xc5\xbb\xfc\x86\x8dv\xed\x94\xb3m\x9b\xb7\x9d\ +\xf4\xc5\x8bU\xb2\xb0\x90\x80\x869\xed\x8bb7;\xc3\ +\xf9Cb\x1d\xca3\x00\x00\xe42\xfa\xb1\x8f_\xd8\xb6\ +H\xd7\xc8\xe0A\xa3}\xc7W\xb6n\xf5\x16\xd2'O\ +&\xa4a\xce\xfa\xb4\xd8\xc6\xcep~K\x22\xdd\x1a\x16\ +\x00\x00 \xe7\xd1\x0b\xe2\xcd\xb6-\xd6\xd5\xc4\xff\xf1\x1b\ +>\x9a5S\xce\xe6\xcd\xdeB\xfa\x80\x01\x845\xcc9\ +\x1f\x13\x9b\xd9\x19\xce\xaf\x13\x0b)\xc7\x00\x00\x00\xffE\ +\xf7J_e\xdb\xa2\xad\xfb1_\xe27\x844i\xa2\ +\x9c\xf5\xeb=]\x1au\xb84\x8a9\xe4\x1dbm\xfb\ +\x82\xf9\x97\x09\x1e \x02\x00\x008(V\xf6J_(\ +&\xfd\x84\x91\xf2r\xe5\xac[w\xe8K\xa3\x1b7*\ +\x87K\xa3\x98\x03\xfeX\xaci_8\xff\x5c\x9cG\xd9\ +\x05\x00\x0084'\x8b\x1f\xdb\x16\xd2'\x89{|\x86\ +\xf4\x94\x87\x9d\xf4\xe4\xc2\x85\xca)( \xc4al\xd5\ +\xf79J\xec\x0b\xe7\x1f\xbb\xb5\x06\x00\x00\x00<\xd2S\ +\xfc\xbdm!}\x80\xf8\x86\x9fpR\xaf\x9erV\xaf\ +>\xf4q\x973\xcf$\xc8a,\xdd.\x16\xd8\x17\xce\ +\xff\xe8\xd6\x18\x00\x00\x00\xf0IK\xf15\xdbB\xfaQ\ +\xe2K~\xba\xbbHHOy\x09\xe9\x03\x07\x12\xe80\ +V\xaev\xefqX6\x87\xdf\x14[S^\x01\x00\x00\ +2\xa7\x9e\xf8\x88m!\xbd\xad\xf8\xac\x9f\xb0R\xb7\xae\ +rV\xad:\xf4\xa5\xd1\xb6m\x09v\x18\x0b\xcf\xb1\xb3\ +S\xcbsbc\xca*\x00\x00@\xd5\xd1m\x18o\xb1\ +m\xb1?\xdc\xef\xab\xa3\xfa2\xe8!B:\x97F1\ +\xea&\xed\x0d\xe7\xf7&\xd2\xef.\x00\x00\x00@\x96(\ +\x10+m[\xf4\x1b\x8a\xbf\xf4\x13`j\xd5R\xce\xf2\ +\xe5\x07\xdfI_\xbaT9EE\x84=\x8c\x9c{\xc5\ +3\xed\x0c\xe77\x89\xd5(\xa3\x00\x00\x00\xc1\xb0\xca\xb6\ +\xc5\xbf\x8e\xf83?;\x8c5k\x1e:\xa4O\x9bF\ +\xe0\xc3H\xf9\xbe8\xd9\xcep~\xa5\xfb\x05\x1f\x00\x00\ +\x00\x02d\xaa\xf8/\x9bB@\xa9x\x93\x9f@#!\ +=y\xc9%\x07?\xee2x0\xc1\x0f#\xe1nq\ +\xac\x9d\xe1|%\xe5\x12\x00\x00\xc0\x1c#\xc4\xbf\xdb\x14\ +\x06\x8a\xc4\xab|\x86t\xe7`!\x9dK\xa3\x18\x01\xdf\ +\x11\x87\xd9\x17\xcc\xf5cg\xe7P&\x01\x00\x00\xccs\ +\x8c\xf8\x07\x9b\x82\x81\xee\xf7\xbc\xc9\xcfq\x97\xb22\xe5\ +,[v\xf0K\xa3\xba\x03\x0cA\x10-\xf4u\xb1\xaf\ +}\xe1\x5c\xff\xba6\x99\xf2\x08\x00\x00\x10\x1e\xcd\xc5W\ +-\x0b\x08\xfb\xbaXx\x0e:5j\xa8\xd4\x92%\x07\ +\xbd4\x9a\xaaV\x8d@\x88V\xf9\xbc\xd8\xce\xbep\xfe\ +\x818\x98\xb2\x08\x00\x00\x10>\xba\xaf\xf1s\xb6\x85\xf4\ +9n\xcb9\xcf\xc7]\x0evqt\xf2dB!Z\ +\x15\xce\xdb\xdb\x17\xce\xff,\xf6\xa5\x1c\x02\x00\x00\xd8C\ +-\xf1>\xdbB\xfa\xa9nw\x0bO\xc1\xa7\xac\xec\xe0\ +\x17G\x87\x0c!\x1cb\xe8>-\xb6\xb0/\x9c\xcbw\ +\xe1Dg\xca \x00\x00\x80}\xe8Vj\xffc[H\ +\x1f.\xbe\x9b\x85\x9d\xf4TE\x85r\xda\xb5#$b\ +h>(6\xb2/\x9c\xffNlB\xf9\x03\x00\x00\xb0\ +\x97\xbc\x84\x85\xbd\xd2\xfb\x89oz\x0dB\xf5\xea)g\ +\xed\xda\x03\xef\xa2\xaf_\xcfK\xa3\x18\x8a\xbfv\x1f\xe6\ +\xb2ln=&\xd6\xa5\xec\x01\x00\x00D\x83\xf9\x89t\ +\xab5k\xc2D/\xb7\xeb\x85\xa7@\xa4;\xb7\xacY\ +s\xe0\x90\xae\xbb\xbepi\x14\x0dz\xbf\xd8\xc0\xbep\ +~\xb7XJ\xa9\x03\x00\x00\x88\x16\x13\xc4\x8fm\x0a\x15\ +]\xc5\x97<\x86\xa2\xd4\xc1v\xd2\xe7\xccQN^\x1e\ +\xe1\x11\x03\xf7\xe7bm\xfb\xc2\xf9\xcdb5J\x1c\x00\ +\x00@4\x19\x9aH\xb7^\xb3&\x5c\xb4s\xbb`x\ +\x0aH\x8d\x1a\xa9\x94>\xd6r\xa0\x90>z4\x01\x12\ +\x03\xf5.\xb1\x96}\xe1\xfc\xdb\x89\xf4}\x13\x00\x00\x00\ +\x880}\xc4\xbf\xd8\x142:\x88\xbf\xf5\x1a\x94\xca\xcb\ +Uj\xc3\x86\xaf\x07\xf4\xcaJ\xe5\xf4\xe8A\x90\xc4@\ +\xbc\xdb\xce\x9d\xf3\xcb\x13\xe9{&\x00\x00\x00\x10\x03:\ +\x8a{l\x0a\x1b\x87\x8b\x8f{\x0dLM\x9b*g\xf3\ +\xe6\xafwv\xd9\xb1C9\xcd\x9a\x11(1\xab\xde*\ +\xd6\xb0+\x98\x7f)\x9eK\x19\x03\x00\x00\x88\x1f\xcd\xc4\ +\xd7l\x0a\xe9\x8d\xdc\xee\x18\x9e\x82\xd3\xe1\x87\x1f0\xa4\ +\xef;\xa7\xae\xdb3\x12,1\x0b\xde,\x96\xd8\x15\xce\ +?\x13\xa7R\xbe\x00\x00\x00\xe2KS\xf1\x05\x9bBz\ +\xb9\xdb_\xdaS\x80j\xd1B9[\xb7~=\xa4/\ +Z\xa4\x92\x85\x85\x04L\x8c\xdb\xce\xb9\x0e\xe7gR\xb6\ +\x00\x00\x00\xe2O\x99\xf8K\x9bBz-\xf7B\x9e\xa7\ + \xd5\xaa\x95r\xb6m\xfbzH\x9f:\x95\x90\x89\x19\ +{\x9dXdW8\xff\xa7x\x02\xe5\x0a\x00\x00 w\ +(\x16\x7fdSH\xd7;\x97\xb7x\x0dT\x9d;+\ +g\xd7\xae\xaf\x87\xf4\xfe\xfd\x09\x9b\xe8\xdb\xff\xb1/\x9c\ +\xeb\xceK\x83(S\x00\x00\x00\xb9\x87\xee\xa3|\x93M\ +!\xbd\xd4=f\xe0)Xu\xeb\xa6R\x15\x15_\xbd\ +4\xaa\xff\xfb\xf6\xed\x09\x9d\xe8\xd9\xeb\xed\x0b\xe7\x7f\x15\ +\xfbS\x9e\x00\x00\x00r\x17\xdd\xb2m\xb3M!]\x87\ +\xa5k\xbd\x06\xac\x01\x03\xbe\xbe\x8b\xae/\x926lH\ +\xf8\xc4C\xfam\xb1\xc0\xaep\xbe7\x91\xee\xb8\x04\x00\ +\x00\x00\x90X\x92H\xb7r\xb3\x22\xa8\xe8\xd0t\xa5\xd7\ +\xa05j\xd4\xd7\xdb/\xaeX\xa1\x9c\x92\x12B(F\ +i\xe7\xfc-\xb1\x05\xa5\x08\x00\x00\x00\xf6gZ\x22\xdd\ +5\xc2\x9a\x90~\x85\xd7\xc05a\xc2\xd7w\xd2\xcf:\ +K9yy\x84Q\xfc\x9a\xdf\xb1/\x9c\xeb\xceJM\ +(A\x00\x00\x00p N\x12?\xb6)\xa4Wz\x09\ +]:\x88O\x99\xf2\xf5\x90>f\x0c\x81\x14\xbf\xe2w\ +\xed\x0b\xe7O\x8a\xf5(=\x00\x00\x00p0\x86\x8a\x1f\ +\xda\x14\xd2+\xbc\x84\xaf\xfc|\xe5\xcc\x9e\xfd\xd5\x80^\ +Y\xa9\x9cc\x8e!\x98\xe2>o\xb0/\x9c?\x22\xd6\ +\xa6\xe4\x00\x00\x00\x80\x17\x06\x8a\x7f\xb3%\xc8\x14\xb9\xad\ +\xf0\x0e\x19\xc2\x8a\x8a\x94\xb3p\xe1WC\xfa\x8e\x1d\xca\ +i\xde\x9c\x80\x9a\xe3\xfe\xc8\xbe\x17B\x1f\x12kRj\ +\x00\x00\x00\xc0\x0f\xba\x9bD2a\xd1N\xfaN/a\ +\xaczu\xe5,]\xfa\xd5K\xa3\xeb\xd7\xabT\x9d:\ +\x04\xd5\x1c\xf5F\xb1\x9a]\xe1\xfc\x8eD\xfa-\x02\x00\ +\x00\x00\x00\xdf\xb4\x13\xf7\xd8\x14\xd2wx\x08d\xc9\xb2\ +2\xe5\xe8N.\xfb\x87\xf4\xc5\x8bU\xb2\xb0\x90\xc0\x9a\ +c\xea\xbe\xfa\xd5\xed\x0a\xe7\xb7'\xd2o\x10\x00\x00\x00\ +\x00dL[q\xb7-\x01\xa7\xd0\xed_}\xc8pV\ +\xb7\xaer.\xbb\xec\xab\xc7]\xce<\x93\xd0\x9aC\xde\ +)\x96\xd9\x15\xce\xe5\x1f\x89\x9ds\x00\x00\x00\xc8\x0e\xcd\ +\xc47\x12\x89\x88\xb5`l\xd2$\xfdp\xd1\xfe!\xfd\ +\xd8c\x09\xaf9\xe0]bM\xbb\xc2\xf9\x8f\x13\xec\x9c\ +\x03\x00\x00@\x96\xd1\xad\xe0~cK\xe0\xc9\x13\xd7{\ +\x09k\xed\xda\xa9\xd4\xce\x9d\xff\x0d\xe8\xbbv\xed\xfb\x7f\ +#\xc4r!\xd4\xa0\xd7\x8b\x05\x94\x10\x00\x00\x00\x08\x82\ +:\xe2c\x91\x0b\xe9]\xba(\xa7\xa2\xe2\xbf!\xfd\xf2\ +\xcbU\xb2Q#\xc2l\x0c\xbd]\xacaW8\xaf\x14\ +\xf3(\x1d\x00\x00\x00\x10$\xb5m\x0a\xe9\xf9\x1e/\x8e\ +:\xc3\x86}\xf5\xa8\x8b\xbeDZRB\xa8\x8d\x91\xf7\ +\x8a\xb5\xed\x0a\xe7\xd7\x8a\xf9\x94\x0c\x00\x00\x000A\xa9\ +x\x9fM!\xdd\xd3\x8b\xa3\x13'~5\xa4\x9f{n\ +\xfa\x81#\xc2m\xe4}@\xackW8\xbf2\xc1\xce\ +9\x00\x00\x00\x18F_x\xbb\xcd\xa6\x90\xbe\xebPA\ +./\xef\xeb\xaf\x8d\x9et\x12\x017\xe2>(\xd6\xb7\ ++\x9c\xaf\xa1<\x00\x00\x00@X\xe8\x8bo\xdf\xb1%\ +\x18\xe9\xee.Wzymt\xd1\xa2\xaf\x86\xf4\xbe}\ +\x09\xba\x11\xf5I\xb1\xb1]\xe1|\x09e\x01\x00\x00\x00\ +\xc2F\xff\x8c\xbf\xcb\xa6\x90~\xd5\xa1\x82]i\xa9J\ +\xad\x5c\xf9\xdf\x80\xbec\x87rZ\xb4 \xf0F\xcc\xe7\ +\xc5\x16\x84s\x00\x00\x00\x80\x03\xa2/\xc2]aKP\ +*\x16o9T\xc0k\xd0@9\x1b7\xfe\xf7\xa5\xd1\ +\x0d\x1b\x94S\xa7\x0e\xc17\x22\xbe&v\xb6+\x9c\xaf\ +\xa6\x0c\x00\x00\x00\x80m\xe8\x9d\xf4u\xb6\x04&\xdd\x07\ +\xfb\xc7\x87\x0az\xcd\x9b\xab\xffk\xef\xfec\xed\xae\xeb\ +;\x8e\x7fo\x7f\xd1\xd6\xda\x9f\x16\x1a\x1bhK\xaf\xa6\ +\x19\xb8D\xaa-m\x88s\xcd\xbaF\x94\x15\x9dT\xc6\ +\xa6\x80\xa3\xb9\x13\x7f\xc4\x94\x8b\xd8\xc9\xc0\x16*k\xb5\ ++\xed\xed6\xdc2\xe6\xb6f,\xe0d\xd9\x961A\ +\x13\xc1X\x7f!n\xc8HQA\x84\xdes\x8d\x1a\xa3\ +\x9bf*\xb4_\xdf\xdf\x9d\xe3N[\xee\xbd\xed\xed\xfd\ +\xf1\xf9\x9cs\x1e\x8f\xe4\xf5o\xd3\x9c\xf3=\xc9\xb3\xa7\ +\xdf\xf3\xf9\xd6\xf6\xeci~\x93\xfe\xfe\xf7\x97\x03\xd3\xa6\ +\x09\xe0\xcc\xf7\xcd\xd8\xab\xf3\x8a\xf3\x9d>\xfe\x00@\xce\ +\xae\xcf%\x9c\xa6\xc7\xee\x19\xe9\x19\xe9W^)\x823\ +\x8f\xf3W\xf9A(\x00\xc0\x88\xf5\x16\xad\xf4M\xfa\xba\ +u\xc7\xffht\xfdz1\x9c\xe1\x9e\x8e\xbd&\xaf8\ +\xbf\xd5G\x1d\x00h%7\xe5\x12R\xd5\xc3k\xee\x1f\ +\xc9\x19\xe9\xfb\xf7\x97\xb5\xf3\xcf\x17\xc5\x19\xedp\xec\xcd\ +y\xc5y\xf5\xc3h\xe7\x9c\x03\x00-gK.A5\ +;v\xdf0\x01\xd8_=\xb0\xe8\x1d\xefhF\xfa\xae\ +]em\xe1Bq\x9cI\x9co\xca+\xceo\xf3\xd1\ +\x06\x00Z\xd9{cGs\x89\xf4O\x9e\xec\x8c\xf4\xf7\ +\xbd\xaf\x19\xe9\xdb\xb7\x97\xb5Y\xb3Dr\xe2]\x9dW\ +\x9c\xff\xb1\x8f4\x00\xd0\x0e\xfe \x97H_\xd0x,\ +\xfc\x90A8gNY\xdb\xb1\xa3\x19\xe9\xef~w\xfd\ +\xdbu\xa1\x9cd[\xdc\xd6\x02\x000nzr\x89\xf4\ +\x85\xb1\x07\x87\x89\xc2\x81\xee\xee\xb2\xb6wo3\xd27\ +n\x14\xcb\x09vc^q\xde'\xce\x01\x80vt]\ +.\xc1uN\xec\xcb\xc3\x05\xe2\xaaU\xc7\x9f\xec\xb2f\ +\x8dh\x9e\xc0\xed\x8fM\xca'\xce?V\xd4\x1f\xc6\x05\ +\x00\xd0\x966\xc7\x8e\xe4\x10^K\x1a\x8f\x8b\x1f2\x14\ +/\xbd\xb4\x19\xe8\xb7\xdf^\xd6\x96.\x15\xcf\x13\xb0;\ +c\x93\xf3\x89\xf3?+|s\x0e\x00t\x80kr\x89\ +\xf4\x15\xb1\xc7\x87\x8a\xc5\xae\xae\xb2\xbf\xa7\xa7\x19\xe9\x1f\ +\xfaP\xfd\x1eu\x11=n\xfb\xe7\xc6\x03\xa62\x89\xf3\ +;\xc49\x00\xd0I~?\x97H_\xd9xB\xe5\xa0\ +\xf7\xa3O\x9f^\xd6>\xf0\x81f\xa4_w]Y\x9b\ +2EL\x8f\xc3\x1e\x8a\xcds[\x0b\x00@R\xef,\ +2\xf9\xe1\xe8\xebb\xcf\x0e\x15\x8f\x0b\x16\x94\x03;w\ +6#}\xd3&A=\xc6{4\xb64\x9f8\xbf'\ +6\xc5\xc7\x13\x00\xe8To/2\xf9&\xfd\x8d\x8d\x87\ +\xe2\x0c\x1a\x91\xcb\x97\x1fw\xb2K\xff\xda\xb5\xc2z\x8c\ +v\xa8q\xabQ&q~wl\xb2\x8f%\x00\xd0\xe9\ +\xdeUd\xf2M\xfaU\xc3\xc5du\x92K#\xd0\x07\ +\xaaX\xf7\xa3\xd1Q\xef\xe9\xd8\xda|\xe2\xfc\xbe\xd84\ +\x1fG\x00\x80\xba\xf7f\x12ie\xef0A\xd9_\xdd\ +\xde\xe2G\xa3c\xb2\xea\x7f+~+\x9f8\x7f(6\ +\xd3\xc7\x10\x00\xe0x\xd9\x9c\x93\xbem\xa8@\xaf\x9e*\ +\xfa\x9e\xf74\xbfI\xef\xed\xf5\xa3\xd1\xd3\xdc\x95\xf9\xc4\ +\xf9\xc3\xb19>~\x00\x00\x83\xdb\x99C\xb4U\xe7p\ +\xff\xd5Pq9sfY\xbb\xf9\xe6f\xa4_~\xb9\ +\xe0\x1e\xe1\xb6\xe7\x13\xe7\xdf\x8c\xbd\xd4\xc7\x0e\x00`x\ +;r\x88\xb7\xa9\xb1\x03CE\xe6\xe2\xc5\xe5@\xf5\xf0\ +\xa2_\xde\xeeR=yTx\x9f\xd2\xf6\xc4\xba\xf2\x88\ +\xf3\xa7b\x8b}\xdc\x00\x00NM\x16\xdf\xa4\xcf\x88\xfd\ +\xd3P\xb1\xb9re3\xd0\xf7\xed+\x07\xba\xbb\x05\xf8\ +Iv\xa0\xf1\x0f\x9f\x0c\xde\xdb\xf8\xeb\x14\xcb}\xcc\x00\ +\x00N]\xf5\x04\xc7?\xcd!\xd2g\xc7\x1e\x18*:\ +/\xbb\xacy\xab\xcbm\xb7\x95\x03s\xe7\x0a\xf1!\xf6\ +/\x8d\x7f\xf0d\xf0\x9e~?v\xbe\x8f\x18\x00\xc0\xe9\ +E\xfa\x1d9D\xfaY\xb1/\x0c\x16\x9e\x93'\x97\xb5\ +-[\x9a\xdf\xa4\xf7\xf6\x96\xfd~4\xfa\x82}66\ +?\x8f8\xff\xef\xd8\xab}\xb4\x00\x00N_\xf5\xd0\x98\ +\xbbs\x88\xf4\x97\xc5\x1e\x1f,@\xe7\xcf/k\xbbv\ +5#\xbd\xfaV]\x94\xff\xff\x1e\x8b-\xcf#\xce\x7f\ +\x1a\xfbM\x1f)\x00\x80\xd1\x9b\x1a\xbb7\x87H_\x1d\ +\xfb\xd6`!\xfa\xf2\x97\x97\xb5\xbe\xbef\xa4_x\xa1\ +8o<\x88hU\x1eq\xfe\x5c\xec\x8d>J\x00\x00\ +c\xa7\xfa&\xfd\x1fr\x88\xf4\xf5\xb1g\x07\x0b\xd2\x0d\ +\x1b\x9a\x81^\x9d\xf0r\xf6\xd9\x1d\xff \xa27\xe4\x13\ +\xe7o\xf2\x11\x02\x00\x18{\xd3c\x0f\xe4\x10\xe9\xd7\x0e\ +\x16\xa5]]em\xf3\xe6f\xa4Wg\xa5\xcf\x98\xd1\ +\xb1\x81~C\x1eq~4v\xad\x8f\x0e\x00\xc0\xf8\x99\ +Q\xd4\x1f\xcb\x9e<\xfen\x1e,L#\xc8\x07\xb6m\ +kFzOO=\xdc;,\xce\xf7\xe5s\xd6\xf9u\ +>2\x00\x00\xe3\xafz,\xfb#\xa9\xe3oR\xec/\ +\x86x\x88Qm\xcf\x9ef\xa4\xaf[\xd7Qq\xfe\xf1\ +|\xce:\xdf\xed\xa3\x02\x000q\xce\x8c=\x91:\x02\ +\xcf\x18\xeaAF\x17]\xd4<\x1f}\xef\xde\xb2\xb6d\ +IG\xc4\xf9\xc1\xd8\xbc<\xe2\xfco\x8b\xfa1\x9d\x00\ +\x00L\xa0s\x8b\xfa\x13!\x93\xc6\xe0\xbc\xc69\xdf/\ +\x08\xd6+\xaeh~\x8b~\xeb\xade\xedE/j\xeb\ +8?\x14\xeb\xce#\xce\xef/\xea'\xff\x00\x00\x90\xc0\ ++b?H\x1d\x85\xe7\xc4\xfe\xf3\x84`\xad\x1eX4\ +p\xc3\x0d\xcdo\xd2\xab\x1f\x90\xb6i\x9c?\x13{M\ +\x1eq\xfe\xd5\xd8l\x1f\x0b\x00\x80\xb4\xd6\x15\xf5\x87\xd0\ +$\x8d\xc3U\x83\x9d\x91\xbepaY\xfb\xc8G\x9a\xdf\ +\xa4\xaf^\xdd\x96\x81\xbe9\x8f8?\x1c;\xc7\xc7\x01\ +\x00 \x0f\xaf\x8f\xfd<u$\xfeF\xe3\xdb\xe4\xe3\x02\ +\xf6\xbc\xf3\xca\xda\xfe\xfd\xf5@\xaf~<\xbahQ[\ +\xc5\xf9\xf6<\xe2\xfc\xbb\xb1n\x1f\x03\x00\x80\xbc\x5c\x11\ +;\x92:\x16\x7f\xefd\xf7\xa3W\xb7\xbdL\x99\xd2\x16\ +q\xfe\xb1\xc6i6\x89_\xf3\x1f\xc7V\xb9\xfc\x01\x00\ +\xf2tm\x91\xc17\xba\x7f4\xc8\xfd\xe8\xb5\xad[\x9b\ +\x91\xbeqc\xcb\xc7\xf9\xa7b\xb3\xf2xJ\xe8\x1b\x5c\ +\xf6\x00\x00y\xdb\x9e:\xd0\xab\x87\xf4\xec?1j\xcf\ +<\xb3\xec\xdf\xbd\xbb\x1e\xe8}}em\xe9\xd2\x96\x8d\ +\xf3Gb\x8b\xf2\xb8\xb5e\xb3\xcb\x1d\x00\xa05\xdc^\ +dxFz\xff\xda\xb5\xcdS]n\xba\xa9\xacM\x9d\ +\xdarq\xfed\xecW\xf3\x88\xf3\xed.s\x00\x80\xd6\ +19\xf6\x89\xd4\x11\xb9 \xf6\xf9\x13#\xfd\xaa\xab\x9a\ +\xb7\xba\x5crI\xcb\x05\xfa[\xf2\x88\xf3\xbf+<\x88\ +\x08\x00\xa0\xe5T\x0f\xab\xf9\xb7\xd41\xb9$\xf6\xd8\xb1\ +\x91[=\xb0\xa8zpQ\x15\xe8\xd5SF\xcf:\xab\ +e\xe2\xfc\xe6<\xe2\xfc\xde\xc6?\xc0\x00\x00hA\xd5\ +Ck\x1eN\x1d\x95\xbf\x1e{\xf6\xd8\xd8\xed\xee\xae\xdf\ +\x87^EzOOK\xc4\xf9?\xc6\xa6\xa6\x8f\xf3G\ +b/vY\x03\x00\xb4\xb6\x05\xb1C\xa9#\xfd\xf2\x13\ +\xa3\xf7\xe2\x8b\x9b\xb7\xba\xacX\x91u\x9c\x1f\x8c\xcdI\ +\x1f\xe7O\xc7\x16\xb9\x9c\x01\x00\xda\xc3\xb2\xd8wRG\ +\xfa\xf6c\xc3w\xf2\xe4\xb2v\xfd\xf5\xf5@\xef\xed-\ +k]]Y\xc6\xf9\x13\xb1\x97\xa5\x8f\xf3\x1f\xc6~\xc5\ +e\x0c\x00\xd0^^U\xd4\x1fj\x93,4\xab\x87\xfa\ +\xfc\xcd\xb1\x01<o^Y\xfb\xf0\x87\xb3\xfd\x16\xfdp\ +lC\x1eg\x9dop\xf9\x02\x00\xb4\xa7\xd7\xc7\x9eO\ +\x19\x9c\xd5\xc3}>}l\x08\xafYS\x0f\xf4\xb7\xbd\ +-\xbb@\xef\xcd\xe3G\xa1\xefr\xd9\x02\x00\xb4\xb7\xde\ +\xd4\xd1\xb9,\xf6\xf8\xb11|\xcd5e\xff-\xb7d\ +\x15\xe7\x07b\x93\xd3\xc7\xf9G]\xae\x00\x00\x9d\xa1/\ +u\xa4_\x14{\xe6\x97A<sfY\xbb\xf1\xc6l\ +\xe2\xfc\xa1\xd8\xec\xf4q\xfe@Q?*\x13\x00\x80\x0e\ +P=\xe4\xe6@\xeaH\x7f\xeb\xb1a<gN\x16q\ +~(\xb64}\x9c\xffG\xe18E\x00\x80\x8e3=\ +\xf6\xd9\xd4\x91\xbe3\xa3\xdbZ\xfac\xeb\xd3\xc7\xf9\xe1\ +\xd8b\x97'\x00@g\x9a_$>#}j\xe3!\ +@9\x04\xfa\x1f\xa6\x8f\xf3\xea\x94\x9d\x95.K\x00\x80\ +\xce\x96\xfc\x8c\xf4\x85\xb1\x87\x13\xc7\xf9]\x8dc \x13\ +\xbe\x0eGb\xbf\xedr\x04\x00\xa0\x92\xfc\x8c\xf4\xf3b\ +O&\x8a\xf3\xaf\xc4^\x92\xfe\xdb\xf3\xad.C\x00\x00\ +\x8eU\x9d\x91\xfe\x5c\xcaH}S\x828\x7f:v\x81\ +\xe3\x14\x01\x00\xc8\xd4\x96\xc4\xa1Z\xde2\xc1\x81\xde\x93\ +>\xce?W\xd4\x7f\xb0\x0b\x00\x00\x83\xda\x972X\xa7\ +\xc4>>Aq~G\xac+m\x9c\x7f+\xb6\xd0%\ +\x07\x00\xc0p&\xc5\xeeM\x19\xe9sc_\x18\xe78\ +\xffLlf\xda8\xffQl\x85\xcb\x0d\x00\x80S1\ +#\xf6\xa5\x22\xf1\x8fF\x9f\x1a\xa78\xffzly\xfa\ +\x13[6\xba\xcc\x00\x00\x18\x89\x97\x16\xf5\x87\xe6$\x0b\ +\xd9\xdf\x1d\xa7@\xbf4\xfd}\xe7\xdb\x5c^\x00\x00\x9c\ +\x8e\xea\xa19?I\x19\xb3\xbb\xc78\xce\xff$}\x9c\ +\xdf\x13\xebri\x01\x00p\xba\xde\x1c;\x9a*h\xcf\ +\x88\xdd7Fq~\x7f\xe3\xcfK\x18\xe7_\x8b\xcdr\ +I\x01\x000Z\x1fL\x18\xb5\xe5\xe2\xd8c\xa3\x8c\xf3\ +'b\xcb\xd2\xc6\xf9\xf7\x8a\xfaS[\x01\x00`\xd4\xaa\ +\x93]>\x912\xd2\xd7\xc7\x0e\x8f\x22\xd07\xa5\xffQ\ +\xe8%.#\x00\x00\xc6Ruk\xc6\xa3)#\xbd\xf7\ +4\xe3\xbc/\xfd}\xe7;\x5c>\x00\x00\x8c\x87\xead\ +\x97\xfeT\xa1;)v`\x84q\xfe`\xfa\xf3\xce\xff\ +\xb5\xa8\xff\x0f\x04\x00\x00\x8c\x8b\xb5\xb1\x9f\x16\x09\x1fb\ +\xf4\xc5S\x8c\xf3\xea\x1c\xf5\x15i\xe3\xfc\x1b\xb1\xb9.\ +\x19\x00\x00\xc6\xdb\x95\x09\xa3\xb7|e\xec\xdb\xa7\x10\xe8\ +W\xa7\x8d\xf3\x1f\xc7^\xe1R\x01\x00`\xa2\xf4\xa5\x8c\ +\xf4\x9e\x93\xc4\xf9\x9d\xe9\xef;\xff\x1d\x97\x08\x00\x00\x13\ +iJ\xec\xd3\xa9\x02\xb8+\xf6\x97C\xc4\xf9\x97bs\ +\xd2\xc6\xf9>\x97\x07\x00\x00)\xcc/\xea\xf7Y'\x09\ +\xe1\xd9\xb1\x83'\xc4\xf9\xb3\xb1\xd5i\xe3\xfc\xc1\xd8T\ +\x97\x06\x00\x00\xa9\x5c\x10\xfb\xdfTA|\xc1\x09\xf7\xa3\ +oM\x1b\xe7\xdf\x8f\x9d\xed\x92\x00\x00 \xb5\xab\x13F\ +\xf1\xff\xfd\x18\xb4\x8a\xf3\x7f\x8fMI\xf7\xf78\x1a\xbb\ +\xd8\xa5\x00\x00@.nO\x19\xe9\xbbbK\xd2~{\ +\xbe\xcd%\x00\x00@N\xa6\xc5>_$\xfc\xd1h\xc2\ +8\x7f\xa8\xa8\xffh\x16\x00\x00\xb2rV\xecp\x91\xfe\ +\x88\xc3\x89\x5c\xf5d\xd53\xbd\xf5\x00\x00\xe4\xea\xc2\xd8\ +\xcf:$\xce\x9f\x8f\xfd\x9a\xb7\x1c\x00\x80\xdc\xbd\xb3C\ +\x02\xfdFo5\x00\x00\xad\xe2\xce6\x8f\xf3\xfbb\x93\ +\xbc\xcd\x00\x00\xb4\x8aY\xb1Cm\x1a\xe7\xdf\x89-\xf2\ +\x16\x03\x00\xd0j\xce\x8f\xfd\xa4\xcd\xe2\xbc:\xef|\x83\ +\xb7\x16\x00\x80V\xb5\xa9\xcd\x02}\x87\xb7\x14\x00\x80V\ +\xd7\xd7&q~\xb0p\xde9\x00\x00m`j\xecs\ +-\x1e\xe7?\x8c-\xf3V\x02\x00\xd0.\xce\x8e}\xaf\ +\x85\x03\xfd2o!\x00\x00\xed\xe6u\xb1#-\x18\xe7\ +\x7f\xed\xad\x03\x00\xa0]\xedj\xb18\x7f26\xc7\xdb\ +\x06\x00@\xbb\xaa\xeeG\xffb\x8b\xc4\xf9s\xb1U\xde\ +2\x00\x00\xda\xdd\xb9E\xfdG\x97\xb9\x07\xfaM\xde*\ +\x00\x00:E\xee\xe7\xa3;R\x11\x00\x80\x8e\xf3\xd1L\ +\xe3\xfc\x7fb\xcb\xbd=\x00\x00t\x9a3b_\xc90\ +\xd0\xdf\xea\xad\x01\x00\xa0Su\xc7~\x94Q\x9c\xdf\xe5\ +-\x01\x00\xa0\xd3\xbd%\x938\xffvl\xae\xb7\x03\x00\ +\x00\x8a\xe2\xef\x13\xc7\xf9\xd1\xa2\xfe %\x00\x00 \xcc\ +\x8b=\x930\xd0\xef\xf0\x16\x00\x00\xc0\xf1^\x1b;\x92\ + \xce\x9f\x8a\xbd\xd8\xcb\x0f\x00\x00/\xb4m\x82\xe3\xfc\ +\xf9\xd8\x1a/;\x00\x00\x0c\xaez8\xd0\xc1\x09\x0c\xf4\ +]^r\x00\x00\x18\xde\xb9\xc5\xc4\x1c\xbd\xf8\xb5\xa2~\ +\x16;\x00\x00p\x12W\x8ds\x9c\xff<\xf6J/3\ +\x00\x00\x9c\xba\xbb\xc61\xd0\xb7{y\x01\x00`d^\ +\x12\xeb\x1f\x878\x7f\xacpk\x0b\x00\x00\x9c\x96\xea\xe1\ +AG\x8b\xb1=\xb5e\x95\x97\x15\x00\x00N\xdf\xde1\ +\x0c\xf4[\xbc\x9c\x00\x000:\xd5\xed(\x8f\x8eA\x9c\ +W\x7f\xc64/'\x00\x00\x8c^u\xe2\xca\xcf\x0a\xa7\ +\xb6\x00\x00@6\xb6\x8e\x22\xd0o\xf3\xf2\x01\x00\xc0\xd8\ +\x9a\x14\xfbL\xe1\xd4\x16\x00\x00\xc8\xc6\xb2bdO\x19\ +\xadNmY\xede\x03\x00\x80\xf1\xf3\xf6\x11\x04\xfa.\ +/\x17\x00\x00\x8c\xbf\xbbO!\xce\xff\xabpk\x0b\x00\ +\x00L\x88\xea)\xa3\x03\xc5\xf0\xb7\xb6\x5c\xe8e\x02\x00\ +\x80\x89\xb3\xa1\x18\xfa)\xa3\xbb\xbd<\x00\x000\xf1\xfe\ +|\x908\xffzl\x86\x97\x06\x00\x00&\xde\xcc\xd8\xa1\ +\xe2\xf8[[\xd6xY\x00\x00 \x9d\x95E\xfdI\xa1\ +U\xa0\xef\xf5r\x00\x00@z\x1f\x8c}\xa3\xa8\x7f\xa3\ +\x0e\x00\x00$6-v\x81\x97\x01\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x0e\xf2\x0b@\ +;\x84\xc7\x9dY\x0c\xd3\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x09\xc0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x9c\x00\x00\x00\xb2\x08\x03\x00\x00\x00\x80\xc0V9\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\ +\x9bx\x00\x00\x00\x07tIME\x07\xdc\x03\x09\x08\x1d\ +0D&N\xa6\x00\x00\x02\xd3PLTE\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\x02\x01\x00\x03\x02\ +\x00\x04\x02\x00\x05\x03\x00\x06\x03\x00\x06\x04\x00\x07\x04\x00\ +\x08\x05\x00\x09\x05\x00\x0a\x06\x00\x0b\x07\x00\x0c\x07\x00\x0d\ +\x08\x00\x0e\x08\x00\x0f\x09\x00\x10\x0a\x00\x11\x0a\x00\x12\x0b\ +\x00\x13\x0b\x00\x14\x0c\x00\x15\x0d\x00\x16\x0d\x00\x17\x0e\x00\ +\x18\x0e\x00\x19\x0f\x00\x1a\x10\x00\x1b\x10\x00\x1c\x11\x00\x1d\ +\x11\x00\x1e\x12\x00\x1f\x13\x00 \x13\x00!\x14\x00\x22\x14\ +\x00#\x15\x00$\x16\x00%\x16\x00&\x17\x00'\x17\x00\ +(\x18\x00)\x19\x00*\x19\x00+\x1a\x00,\x1a\x00-\ +\x1b\x00.\x1c\x00/\x1c\x000\x1d\x001\x1d\x002\x1e\ +\x003\x1f\x004\x1f\x005 \x006 \x007!\x00\ +8\x22\x009\x22\x00:#\x00;#\x00<$\x00=\ +%\x00>%\x00?&\x00@&\x00A'\x00B(\ +\x00C(\x00D)\x00E)\x00F*\x00G+\x00\ +I,\x00J,\x00K-\x00L.\x00M.\x00N\ +/\x00O/\x00P0\x00Q1\x00R1\x00S2\ +\x00U3\x00W4\x00X5\x00Y5\x00Z6\x00\ +[7\x00\x5c7\x00]8\x00^8\x00_9\x00`\ +:\x00a:\x00c;\x00e=\x00g>\x00h>\ +\x00i?\x00j@\x00k@\x00lA\x00mA\x00\ +nB\x00oC\x00pC\x00qD\x00sE\x00t\ +F\x00uF\x00vG\x00wG\x00yI\x00zI\ +\x00{J\x00|J\x00|K\x00}K\x00~L\x00\ +\x7fL\x00\x80M\x00\x81M\x00\x82N\x00\x83O\x00\x84\ +O\x00\x86P\x00\x87Q\x00\x88R\x00\x8aS\x00\x8bS\ +\x00\x8eU\x00\x8fV\x00\x91W\x00\x93X\x00\x94Y\x00\ +\x95Y\x00\x96Z\x00\x98[\x00\x99\x5c\x00\x9c^\x00\x9d\ +^\x00\x9e_\x00\x9f_\x00\xa0`\x00\xa1a\x00\xa2a\ +\x00\xa3b\x00\xa4b\x00\xa5c\x00\xa6d\x00\xa7d\x00\ +\xaaf\x00\xacg\x00\xadh\x00\xafi\x00\xb0j\x00\xb1\ +j\x00\xb2k\x00\xb3k\x00\xb4l\x00\xb5m\x00\xb6m\ +\x00\xb8n\x00\xbap\x00\xbbp\x00\xbcq\x00\xbdq\x00\ +\xber\x00\xbfs\x00\xc0s\x00\xc1t\x00\xc2t\x00\xc3\ +u\x00\xc5v\x00\xc7w\x00\xc8x\x00\xc9y\x00\xcay\ +\x00\xcbz\x00\xccz\x00\xce|\x00\xcf|\x00\xd0}\x00\ +\xd1}\x00\xd2~\x00\xd3\x7f\x00\xd4\x7f\x00\xd5\x80\x00\xd6\ +\x80\x00\xd7\x81\x00\xd8\x82\x00\xd9\x82\x00\xda\x83\x00\xdb\x83\ +\x00\xdc\x84\x00\xdd\x85\x00\xde\x85\x00\xdf\x86\x00\xe0\x86\x00\ +\xe1\x87\x00\xe2\x88\x00\xe3\x88\x00\xe4\x89\x00\xe5\x89\x00\xe6\ +\x8a\x00\xe7\x8b\x00\xe8\x8b\x00\xe9\x8c\x00\xea\x8c\x00\xeb\x8d\ +\x00\xec\x8e\x00\xed\x8e\x00\xee\x8f\x00\xef\x8f\x00\xf0\x90\x00\ +\xf1\x91\x00\xf2\x91\x00\xf3\x92\x00\xf4\x92\x00\xf5\x93\x00\xf6\ +\x94\x00\xf7\x94\x00\xf8\x95\x00\xf9\x95\x00\xfa\x96\x00\xfb\x97\ +\x00\xfc\x97\x00\xfd\x98\x00\xfe\x98\x00\xff\x99\x00\xff\xff\xff\ +s\xb6\xc7\xfa\x00\x00\x00\x08tRNS\x00\x09\x0e\x1b\ +(=\x5cr\xeeu#\xcb\x00\x00\x00\x01bKGD\ +\xf05\xb8\xefT\x00\x00\x06RIDATx\xda\xed\ +\x9c\xf9_\x94U\x14\xc6\xad\xacf\x18mTP\xc0\x04\ +\xc4\x85E\x05\xc1\x0d\xc9P\xd1\xc8\x5cZ\x15\xb5\xc5$\ +\xca4\xcb4\xcbJ\xcd\xca\xd2\xd4RJ\xcd\xca4\xb2\ +\x12\xcd\xcaL\xb1 \x90\x08DS@\xf6M\xf6\x01F\ +\x99a\xe6\x9d\x7f!\xd6\x98\xe5]\xeer\xee0\x9f\xbc\ +\xcf\xcf\x9c\xf7~\x99y\xdf\xf7\x9e\xf3\x9cs\xa7_?\ +...........W\xd5\x1dw\xbb\ +\x88\xfa\x8b\xc0\xdd\xa9r\x11\xdd\xc5\xe1n)\xb8dc\ +\x9f\xaa@\x16.\xc5\xd2\xa7*\xe3p\x1c\x8e\xc3\xc1\xc1\ +\x99]\x18\xae0\xe4G\xe2\xa5u\x8c\xe1\xcaBT\xda\ +S\x84lY\xbe;\x98\xc2U\x84\xb6\xff\xcd\x903D\ +l\x17\x86\xabT\x9b\x19\xc2U\x85un~\xee\xbf\x11\ +\xb0\xa5{w\x84\xbe\xcd\x0c\xae6\xa2{kv?\x8b\ +\xcd\x96\xe6\xdd\x15\xbaI`\x03W\x17\xf9_\xe2\xe0~\ +\x0e\x93\xedO\xaf\x9e\xd0\x97\x05\x16pM\xd1Vi\x8d\ +\xc7y,\xb6T\xaf\xde\xd0\x97\xcc\xf0p\xcdsm\x92\ +.\xcfT\x0c\xb6d\x0f\xeb\xd0\xb86h\xb8\x96\x18\xbb\ +\x94\xd0+\x0d\x99\xed\x9c\x87m\xe8\xb3m\xb0p7\x1f\ +qHX\xbd\xd2\x11\xd9\xcez\xd8\x87>c\x84\x84k\ +}L$\x9d\xf6\xbe\x80\xc4v\xc6\xdd1tI+\x1c\ +\x9cq\xb9h\xb2\xef\x9d\x81\xc0\xf6\xab\xbbX\xe8\xe37\ +\xa1\xe0\xda\x9e\x96(E|\xb2\x15\xd9N\x0f\x11\x0f}\ +\xf4\x06\x0c\x9c\xf9y\xc9B\xc9\xf7\xa2\x02\xdb\xc9AR\ +\xa1\xf3\x9a \xe0\xcc/\xca\x94q~9\xb2l'\xb4\ +\xd2\xa11:z8a\x8dl\x91\xe9wI\x86-I\ ++\x17\x1aUG\x0d\xf7\x9aB\x09<\xf2\xb2$\xdbq\ +\xad|\xe8\x8cZJ\xb87\x14\x0bt\xff\x7f$\xd8~\ +\x18\xa8\x14\x1aYM\x05\xf7\x1e\x82}06_\x94-\ +Q\xa3\x1c:\xa9\x9c\x02n'\x92\xb9\x11pM\x84\xed\ +\x1b\x0dJhX\x191\xdc.D\xeb%\xb0\xc0\x81\xed\ +\x88\x06-4\xb8\x80\x10\xeecdc(\xb0\xd0\x8e\xed\ +k\x0djhP>\x11\xdc~5\xbam\x15Td\xc3\ +vX\x83\x1e\x1a\x90G\x00w\x10\x83M\xa5\x0a\xb5\xbe\ +y\xbet\xc3\x09\xf5\xcf\xc1\x86;\x8a\xb5@;]9\ +\xd1G\xde\xf9\x22\xcf\xc6\x84K\xd4\xa805\xb1\xa2;\ +\xf435n\xa8\xef\xdfxp\xcb\xf0\xed\xd2\xc8:\x82\ +\xef\xb4{\x9f\xc5\x833.\xc5_\x22\xbc\xb2=0A\ +\x8d\x1f\x18Q\x8dy\xcf\x19b\x09\x16\xa9\xb1\xec#`\ +\x8b\xaa\xc7~Z\x0dK\xf0\x97\x99\xfe.\x81{>\xb3\ +\x9e\xe0=gX\xec\x14g\x7fV\x03\xd1\x0eqc\x91\ +\x13\xd8f7\x12\xee\xad\xfa\x85\xcc\xd9\xa2\x1b\x89\xb3\x12\ +\xfd\x02\xc6l\x0f\xb5P\xe4s\xfa\xf9L\xd9\xe6\xb7P\ +e\xc2-\xf3\x18\xb2-l\xa1\xac!t\xd1\xcc\xd8\x16\ +\xe9\xa9K\xc3\xc6Y\x8c\xd8\x1e\xd6\x03\x14\xd5\x8d3\x99\ +\xb0\x89\xf9%\x04vDC\x14\x03\xb6\xd8V #\xa7\ +\xe1~p\xb6\xa5\x060\x0b\xacf\x1a0\xdbr\x03\xa0\ +yX=\x15\x94\xedI\x03\xa8\xedz}\x0a \xdbS\ +\xa0\xcef\x07\xddd0\xb6\xe7L\xe0V\x7f\xd5$ \ +\xb6x\x13\x83&Ie8\x08\xdb\x0b&&\xed\xa5\xd2\ +\x09\x00l\xabL\x8c\x1as%\xe3\xa9\xd9V\x9b\x99\xb5\ +4\x8b\xc7Q\xb2\xad\x13\x186\x83\x8b\x83\xa9\xd8^\x15\ +\x98\xb6\xd1\xf3\xc6P\xb0m\x10\x18\x0f \xe4\x92\xd3m\ +Tb\xa3\x1f\xdd\xc8\x1dM\xc8\xf6\xba\x22\x1b\xc0\x5c\xc9\ +\xd5QDl[\x9d3\xf4\xf2\xd7=\x04l\xdb\x9c3\ +\x91\xd3\xfc \xc9\x07\xb7\xc9)pM1d\xb7\xdc\x9b\ +N\x80kz\x80\xf4a\xdd\xce\x1cN7\x97\xfc5\xf7\ +!c\xb8z\xaaZg'S\xb8:\xcaJ\xe7#\x86\ +p\xb53h\x93\x92]\xec\xc6\x85\xee\xa3O\xe7\xf60\ +\x82\xab\x89\x04\xc85\xd5\x09L\xe0\xaa\xa7\x83d\xe9\xea\ +O\x19\xc0U@\xd57\xea\xfd\xe0p\x15\xe1*(\xa9\ +\x0f\x00\xc3\x95\x87\x01\xd6\xd4\xea\x83\xa0pe\x13A\xdd\ +\x08\xb7\xc3\x80p\xa5\xa1\xc0>\x8e\xdb\x110\xb8\xc2`\ +\x15\xb44G\x81\xe0\x0a\x82\x18x\x87\x9aD\x10\xb8k\ +\x81L\x5cW\xcd\xb7\x00p\xf9l\xd8\xda\xe9\x8eQ\xc3\ +\xe5\x050s\xfa\x07&Q\xc2\xe5\x8ee\xd8#\xd1\x9e\ +\xa0\x82\xbb\xe4\xcf\xb4\xbb\xa4=I\x01\x973\x92q_\ +\xce~\x08\x1f\x03\xee\xa2\x1f\xf3\x8e\xe6\xa0\x9f\x08\xe1\xb2\ +\xd9\xb3\xd9\x1f\x11@\x86\xcb\xf2\xc5_j0\xfe\xf8\x81\ +\xcd\x10>*\x5c\xc7\xf1\x05\x5cy\xa6\x10\x0cnX\x0f\ +\xe1#\xc2\xa5{\xe3\xb3\x0d\xcf\xb0X\xf6\xe1\x87y$\ +c\xc2\xa5\x11\xb0\xdd\xdb9\xd3\xbc\x97\x80\xee<\x1e\xdc\ +\x1a\x92\xef\xb4+t;~\xe8\x846,8\xd3j\xdc\ +\x05Fd\xf6\xfc\xfb\x9f`\x87fa\xdes\xc2z\xbc\ +\x05|2{o\xeb\x0f0o\x87L\xec\xa7U\xd8\x88\ +\xb3\x80\xbf\xcd\xb4\xf0\xfb8\xa1\xc3RI^\xc2\xef\xa0\ +/0\xcanVx\x1bz\xe8\xd0\x14\xb2\xed\x0b\xf9\xd6\ +\x1e}\xc5>\xbd\xd8\x8a\xfc\xa4\xfeA\xba\xf1\xef!e\ +\xb3X\xb6 n)\xa7\xc9S&\xa4a\xdc1W\xc5\ +\xca\x81\xcdH\xfb\xfe/4\xc9\xe6\x01\xe5\xed(\xb8P\ +\xb4\x90\x126 \xe4\xc2\xc7\xe9\xd2\xf4\xcf\x95&0\xc7\ +\x15I\x14\xc8\xca/\xa3\x01\xdf\xd3\x168_\xc8\xd3\x8d\ +/\x964>\x84u\xd8\x955vixl\x80\xdc\xc6\ +S,ch\x09\xaf\xc8\xb2}\x05QT\x7f'}\xae\ +!\xa4D\xd6\xa8\x14\xd6\xca\xb89\x87`\xec\x88S\x83\ +%\x16\x08-U0\xa0\xcd\xab$\xe1\x12\xa0\x8c\x9c\x9f\ +\xc5\xcfGM\xaeTl,H\x9e|\xda\x0bg\x81%\ +\x0f\x15\xb9\xfe\x94*\x84\x86\x91)^\x94m\x07\xa4y\ +\xf8\xfb0\x87\xebO\xbd\x8et\x9a\xcf\x14\x87\xd1B$\ +\xb4]S<\xed\xae?\x0d\x8d\xad\x9dn\xa5\x03\xdb\x16\ +h\xc3:c\x84\xcd\xf5#\xaa\x91O\x90\x9aV\xd8\xb1\ +\xbd\x05o\xf5g\xfaX]\xdfjd[Y\xc6e\xa8\ +\xe3\x1b\xe4M\x92\xcb\xbd\xeds\xeb\x91m\x04\x19\xac\x8f\ +\x08\xac\x15\x98\xb4\x97\xae\xf4\x0cF\xcc\xc6c\xb39\x22\ +\x10of\xd4\x98+\xec\x1a\xc8\xb1\x1d\xd9F\xa3\xeb\x19\ +\xc2\x8f31ki\x16u\x8cZ\xcd\xd1Y\xf0\xd5\xfa\ +D'\xdb\x0a\x13\xc3fpI\xa8\xc3\xc86\xa2:\x8f\ +\x08\xc4\x1a\x99\xb6\xd1\x8bW6Z\xc8\xa4_\xa0Zl\ +`?WB(\xdd\xfaf\x8b\xcb\xc29g\x22\x87\xc3\ +q8\x0e\xe7\x02p\xbb\x93\xfaT\x87d\xe1\x5cA\x1c\ +\xee\x96\x81\xbb\xad\xbf\x8b\xe8v\xfe\x83\xac\x5c\x5c\x5c\x5c\ +\x5c\x5c\x5c\x5c\x5c\x5c\x5c\xffC\xfd\x0b\x99\xa5\x5c~G\ +q`B\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00/`\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x01[\x00\x00\x01\x5c\x08\x06\x00\x00\x00f\xca\x1dU\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\ +\x9bx\x00\x00\x00\x07tIME\x07\xdc\x03\x09\x08\x1f\ +%\x1b\xcd\xc8\xcf\x00\x00\x00\x06bKGD\x00\xff\x00\ +\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00.\xe0IDATx\ +\xda\xed\x9d\x09t\x15U\xb6\xfe\xaf\xb6C\xdb-\xdc\x9b\ +\x00b\xdb\xb4\xa2\xb6\xf6\xa0\xdd\xb6\xa2>q\xa0\xaa\x92\ +0*\x8a \xa2\x88\x8a8\xb7-\x88\xa08a\xa7E\ +Q[[\x14'\x22!u+\x84\x00\x81\x10H \x10\ +\xa6@\x98\xc7\x80!\xcc\x90\x90\x89\x84\x04\x12\x12\x12\x12\ +\x02\xa9W\xbb\x82\x1aHn\x86\x9b[u\xeb\xd4\xf9~\ +\xff\xf5\xad\xf7_\xbd^?\xaa\xce>\xe7\xcb\xb9\xa7\xf6\ +\xd9\xdb\xe1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x18@\x07Y\xbc2P\x11\xba\x06\xc8B_\x97,\ +\x0eu\xb9\xc5QNE\xfcX\xfb\x9f\xe1\x9a\xe24\xa5\ +\xb8\xdcB\xba\xa6\x03\xb5\x12\x0b5\x1d\xd3\xfe\xff\xc7\xb5\ +\xff\xa9\xd6\x97\xfe\x9f\x1f\xab\xfd\xdf\xfb\xe9\xbf\xa3\xff\xf7\ +Wj\xff\xd9\x1cM\x93\x9dni<\xfd;\xf4\xef\xd1\ +\xbf\x1b(\x8bw\xd1s \x1a\x00\x00v\x09\xebrq\ +\x80\x12\xfcw\xcd\xe0\x06\xe8\x06\xe7\x16\xbfq*\xc2\x82\ +Z\x03\x14+\x1a6L\xbf\xa9\xe2\xecs\xcd\xd7\xf4\xb5\ +K\x91^w\xc9R\xff\x00\xb9\xdb\xdf\xe8=\x10L\x00\ +\x80\xffQ\x1d\x17\x04\xba\xa5\x9b\x9c\xb20P\xdb1\x86\ +jf\x95\xa0)\xcfbf\xdaZ\xe5\xe9\xef\xa5\xbd\x1f\ +\xbd'\xbd/\xbd7\x82\x0f\x000\x8e\x89\xbd/\x0d\x8c\ +\x08\xba\xdb\xe9\x16Gk\xe63W\xdb\x11\xe6\xda\xccX\ +\x9b)\xfd\xbd\xe9\xb8c\x14\x1d\x878b\x06^\x82\xc9\ +\x01\x00\xf0\x9a6Jp;\x97[z0\xc0-|\xaa\ +\x19\xcb*\xcddO\xf2i\xae\x8d\xeb\xec\xb8\xa4\xd0\xb9\ +3\x9d\x07\xb7\x0d\xef\x19\x88\xd9\x03\x00ht\xe7Jf\ +\xa1\x99k\xd8\xd9\x0fS0S\xefw\xbf\xf4\x91\xee+\ +\xcd\x80Ch\x5c1\xb9\x00\xe0\x9c\xc0(\xb1\x93\xb63\ +{V3\x88Yg\xbf\xe8\xc3(}o\xbcG\xb5?\ +`3]\xb24\xac\x9d\x12\xf4{\xcc:\x00\xf89\x1e\ +\xb8\xb1\xf6\x83\x96\xfe\x15\x1efh\xbe\xf9\xa6\xd3\xf8\xb7\ +\x95\xbb\xdd\x80\xd9\x08\x80\xcdp\xba\x83\xae\x87\xc1Z\xd7\ +x\x9d\x11!\xd7a\x96\x02\xc0(\x9db\xba^\xe6r\ +KOi\x8bz\xa9\xa6\xd306K\x8b\xe2\xb38@\ +\x11\x87t\x96\xc5_c\xf6\x02\xc0\xc2.V\x11C\x02\ +\x14)\x06\xd9\x03\xcc\xaa\xd4\xa5H\x91\xfa\xc75\x00\x80\ +\xe5\xcea\xdbi\x8bs\x8cf\xb0;aV\xf6:f\ +\xa0\xb8\x22\x9d\x0c\x00?\xe3\x92\xc5\xce\x94b\xe4\xb9n\ +\x00d\x13\x95h\x9a\xe0\x0a\x0f\xba\x06\xb3\x1e\x00\x93\x8f\ +\x0aj\xaf\xc7\x0ag`D\x5c\xedt)\xde\x09\x01\x91\ +\xe2\xbdX\x05\x00\x18E\xb2xQ\xed\x07/a\x0bL\ +\x07\xd2\xb4\x99\xe6\x83#f\xe0\xaf\xb08\x00\xf0\x05\xa1\ +\xa1\x17\x06\xc8\xd2`\xa4mA\x1e\x94\xa6\xfd\xd2\x19D\ +\xf3\x04\x8b\x05\x00o\xd0v,N\xb7\xf4\x82\xb6\x982\ +`(P3j4\xec\xc2N\x17\x80\x96\xa0:.\xd0\ +\xcb\x16b'\x0by\xa7\x1d4\x7fP\x0a\x12\x80Fp\ +EJ\x82\xb6XV\xc30 \x1f|L[\x89\x0fi\ +\x00\x9c\x07u\x068{\xd3\x0b&\x01\xf9ZK4\xd3\ +\xbd\x19\xab\x0cp\xcd\xe5\x11\xf7u\xa8-i(V\xc3\ +\x14 \x03u\x8a\xe6Y\x9bh\xb1=V\x1d\xe0\xed\xe3\ +\xd7%t3\x08e\x0d!\xb3\xcb=\xba\x14q\x04\xa5\ +\x11b\x11\x02\xfb\x1f\x19\xb8\xa5{\xb4\x89\x9f\x8a\x85\x0f\ +\xf93G\x97:\x0cc5\x02[B\xf5\x0b\xa8@\x0c\ +\x16:d\x11\xd5P\xc1\x1b\xd4]\x00\xb6\xe2l\xa9\xc3\ +|,p\xc8\x82\xf9\xb9\x87\x9d\x8a\xf8\x08V)`\x1a\ +j;s\xb6\xc57\x166\xc3\xfaG\xec\xe3\xeaK\xab\ +\xc6\xab\x13\xd2\xa2\xd5y\x99+\xd5-\x85\xbb\xd4\xbd%\ +\x87\xd4\x8c\xd2<u\xdf\xf1l5\xb5h\x8f\x9a\x98\xb5\ +F\xfd&=F\x1d\xb1\xf6s\xf5\xff\xe6>\xad\x06\xb8\ +%\xd6\xde3\x01m{\x00\xa3g\xb3\xc2\xe3\xda\x04.\ +\x84Y\xb1\xa9\xee\x0b^Q\xbf\xdf9[\xcd9Q\xa0\ +zCQe\x89\xaa\xec\x9d\xaf>\xbcx\xb4\x1a\xa8\xb0\ +b\xbcB\x81\xd3-=\x8a\xd5\x0b\x989\x9b\xd5&\xee\ +\x1c\x18\x16{\x22S|v\xe58}\xa7\xeaKh\xf7\ +;r\xdd\x17\xea\x15\x91!l\x8c\x85\x22\xc4\xd2<\xc6\ +j\x06\xd6\xdd\xcd\xcaR\x1f\x9c\xcd\xb2\xa9\x9e\x89\xff\xf2\ +\xb9\xc9\x9e\xcf~\xcdt\x07-}\x9b\x99\xb3\xdc@Y\ +\xec\x85U\x0d\xac\xc5\xc4\xde\x97\xd6\x16\xf1\x16k`\x5c\ +l\xa9\xe3\xd4\xee\xea\xa4\x9d\xb1j\x8d\xf6\xff\xcc\x82\xce\ +};G\xf7e#cA\x9b\xd7\x94\x17\x8eE\x0e\xfc\ +\x0e\xb5\xa4\xd6&\xe4\x06\x18\x17{\xbaqf\x7fuC\ +\xc1\x0e\xd5\x1f\xd0\x07\xb6\xdb\xe7\x0cae\x97\xbb\x16\x1d\ +\x80\x81_q)\xe2\xd3h\xac\xc8\xa6\xba\xce}F\xcd\ +\xf6\xf2\xe3\x97\xaf(\xae*U\xfb.\x1a\xc9\xca\x98\x95\ +\xe9\xd5\xc4\x000\x95\xb0.\x17\x9f\xadi\x00\xe3bP\ +\xdd\xe2\x9fWK\xaa\xcaT+Pu\xa6Z\x1d\xb0\xe4\ +Mv.B\xd0\xb1\x02\xae\xfb\x023\xf8\xed\xe4\xe0\x8e\ +T\xbe\x0e\xa6\xc5\xea\xd1\xc1\xc3^\xa7s\x19E\xe9\xa9\ +r\xf5\xce\xb8\xa7Y\x1a\xc7\xe4\xcb#{\x5c\x017\x00\ +\xc6\x9d\xcf*Awj\x13-\x1b\xa6\xc5\xa6\xda+\xc1\ +\xea\xea\xfcm\xaa\x15\xa13\xdc?L\xeb\xc3\xd2xf\ +\xb5\x95\x85;\xe0\x0a\xc0\xe7P\xb2\xb76\xc1N\xc0\xb4\ +\xd8\xd5'\xdb\xdc\xaa\x95\x99\xb6o!kcZ\xe6\x92\ +\xa5\xfep\x07\xe0\x1bBC/<\x9b\xd6\x05\xc3bX\ +\xf4\xe5\xbf\xf2t\x95\xa5\xcd\x96\xd2\xcf\xee_8\x82\xbd\ +\x826\xb2\x18\x8a6<\xa0Ut\x8a\xe9z\x19*u\ +\xd9C\x0b\xb2V\xab,\x90~\xec\x00C\xd7{\xebH\ +\x16\xdd\xc8\xc7\x05^A]\x14(\xbf\x10F\xc5\xbe\xee\ +\x8b\x7f\xce\xd4K\x0b\xade\xc8\xf2\xb1\xac\x8e\xf5jt\ +\x83\x00-\xa2\xcd\x14\xe9O\xda\xc4\xd9\x0f\xa3\xb2\x87\xe8\ +,\x94%\xd6\xe4ogy\xbc\xf7\xd1E\x1f\xb8\x08h\ +\x12\x97\xd2\xedV\xba\x17\x0e\x93\xb2\x87~\x1f\xd5[-\ +;U\xce\x94\xd9\xd2.\xfc\x96\xd9\x8f\xb3\xdc~'7\ +@\x09\xfe;\xdc\x04x\xce8\x88\x08\x0aB\xc6\x81\xbd\ +D?\xc9Y\xe4\xbdM\xdf\xb1>\xf6%\x81\x11Aw\ +\xc3U@}\xa3\x95\x85\xee\xda_\xe4r\x18\x94\xbd4\ +yW\x1c\x93f\xbb$g\xbd\x1d\xc6\xff\x84S\x11C\ +\xe0.\xa0\xce\xd1\x81\xf4\x9061*aN\xf6\x93\xd1\ +e\x13\x8d\x82\xae\x13\xdb$\x06\xda\xba\x92\x1e\x84\xcb\x00\ +\xba\xac0@\xdb\xd1V\xc1\x98\xec'jMS^}\ +Re\x15\xbaZl\x93\x16\xeaU\xb8\xfc\xc0\xfd\x8eV\ +x\x18Fk_\xfdqF?\x95eB\xe6\xbfl\xa3\ +xh\xebL\xfb\x05\x09\xd7\xe1sGK\xd7oO\xc3\ +\x94\xec\xab[c\x073m\xb6\x03\x16\xbfa\xb7\x98\x9c\ +F\x99F\xce\xd0~^\xde\x8f\x1d\xad\xfdu\xf7\xbca\ +L\x9b-\xc3\x97\x1b\x1a\xdd\xe1R\xfb(\xb8\x10\x0fG\ +\x07\xb2(jA\xaf\x80\x19\xf1\xd1\x82\x9ce\xfa/\x1e\ +m\xd7\xd8T\xb8\x22%\x01nd\xe7\x1dm\xa4x/\ +\xf2hqf\x8b3[K\xecp\x8f\xa3D\xa3}\xcf\ +h\xbbP\xa25L\x88\xafl\x84R\xc6n\x8f\xd5\x85\ +\xfeX\xd8<F\xc5tc\x13\xeed#\x02\xa3\xc4N\ +Z`s`@\xfcis\xe1.&\x8d\xb6\xa8\xb2\x84\ +\x97\x18e\xb5\x9f\xd2\xfd*\xb8\x94\x1dv\xb4\xd3\xee\x0d\ +p\xba\xc5\x9d0\x1e\xdc \xc3\x0d2\xcb\x1e)\xa4\xbb\ +d\xd1\x05\xb7b\x99\x89\xbd/\xd5\x82\xb8\x02\xa6\xc3\xaf\ +\x1e[\xf6\x0e\x93f;f\xc3D\xdeb\x95\x8cz\xb8\ +,g\x1e\xb8E\x19\x86\x83\xaa_\xa8\xfa\xc5\x88\x14a\ +\x0a\x5c\x8bM\xa3}\x0ff\x03\x91\x22\xf6\xc43e\xb6\ +\xcbs7\xf1\xfbQS\x16\xdf\x82{\xb1\x95y@\xf5\ +\x0e\xce\xc0h tj`\xee\xfc\xf6\x0c\xae\xf52\x94\ +\xe2\xe5t\x8b'a2P]\xc5\x1e\x5c\xc6\x84\xd1n\ +<\xb2\x03\xf1r\x8b\x15\xce\x88\xa0\xdb\xe0f\x16\x86\xfa\ +\x1f\xb9\x141\x13\x93\x15Bw]\xe6\x95\xd1F\x09n\ +\x07W\xb3\x221\x03\x7f\xa5\x05h\x09&)\xe4I\xef\ +o\x9edi\xb3\x0d\xdf=\x17q:\xe7R\x8a\x90D\ +\xeb\x1a\xe6f\xbd\x0fb\xe30A\xa1\xc6\xd4^\x09V\ +W\xe7o\xb3\xa4\xd1\xee-9\xa4\xfeaZ\x1f\xc4\xa9\ +^\x86\x82\xf8o\xb8\x9b\xe5>\x88\x895\x98\x9cPS\ +\xa2\x82\xdc9'\x0a,e\xb4t\xa5\xf8\xce\xb8\xa7\x11\ +\x1f\x0f\x1f\xcc\xa8J\x1f\x5c\xce\x0aF\x1b\xd9\xedZ-\ +(\xc70)\xa1\x96\xd4\xb9=\x5c^d\x09\xa3\xa5\x1c\ +\xe0\xe0\xf9/!.\x8d\xab0 2\xe4j\xb8\x9d?\ +\x09\xebr\xb1\x16\x88\xcd\x98\x8cPK\xd5u\xee3j\ +\xb6\x9fw\xb8\xc5U\xa5j\xdfE#\x11\x8f\xe6]x\ +X\xe3H\x16/\x82\xe9\xe1\x9c\x16b\xf2H\xa1\xbf\xba\ +\xa1`\x87\xdf\xceh)C\x02qh\x89\xa4\xf7\xe1z\ +\xfe0\xdaHI\xc0\xc5\x05\xa8\xb5j\xa7\x04\xa9\xa1\x9b\ +\xc3\xd4Sg\xaaMK\xef\x9a\xb43V\xed8\xb5\x07\ +\xc6\xbf\xe5\xaa\x0eT\x84\xaep?\x13\x09\x8c\xea\xddV\ +\x1b\xf8\x83\x98|\x90\xaf\xd43\xf1_\x86\xb7=\xdf\x7f\ +<[\x1d\xb4\xf4m\x8cw\xeb>\x98\x1d\xa0\xf5\x0f\x17\ +4kW\xabH\x91\x98t\x90\xaf\x15\xa8H\xea\xb3+\ +\xc7\xf9\xdct\xf7i&;r\xdd\x17\xea\x15\x91!\x18\ +g\xdf\x1c'D\xc0\x05\xcd0ZY\xec\x87\xc9\x06\x19\ +\xad\xee\x0b^Q\xbf\xdf9\xdb\xeb41*\xfe\xad\xec\ +\x9d\xaf>\xbcx\xb4n\xe2\x18S_\x17\xac\x11\xfa\xc2\ +\x0d\x0d\xe4\xf2\xc8\x1eWh\x03]\x84\xc9\x06\x99)j\ +\x1c\xf9\xd2\xaa\xf1\xea7\xe91\xea\xb2\xdcM\xea\x81\xd2\ +\x1c5\xa34\xef\x1c\xa5\x1c\xde\xaa\x17*\x1f\xb1\xf6s\ +\xf5\xff\xe6>\xad\xb7\xe4\xc1\xd8\x19\xaa\xfc\xb6\xe1=\x03\ +\xe1\x8a8>\x80 \x08\xf5o\xd9\xa4m\xa4\xd4\x13\x13\ +\x0c\x82\xa0:\xaaq*b\x08\xdc\xd1\x87t\x88\x11/\ +G5/\xa8\xb5\xea\x1c\xdd\xb7IQ\xee-\x1d\x1b4\ +%\xaa\x91+&\xbc\xd0\xa8\xa8\x15y\xbf\xa4QMj\ +\xf0\xb2w\xd5\xa1+B\x1b\xd5\x93\xc9c\x11\xc3\x86\xb5\ +\xafSL\xd7\xcb\xe0\x92>\xfb(&\xfc\x0f\x93\xea\x5c\ +\xfd%\xe6\x11u\xd4\xba\x09\xea\x84\xb4h\x8f\xfa*m\ +\xba*\xefIhR3\xf6'\xa9q\x19\xc9M\x8a:\ +\x08$\xe7mnTk\xf2\xb7\xeb_\xf3\x9b\x12}\xa1\ +?\xff\xdc\xf3|e\x95\xe5\xeb\xb7\xac\x9aR\xe5\xe9S\ +*\x0f\xfcm\xf6 \xcc\xfd\x06\xa4\xedn?\x86K\xfa\ +\x22\xa7V\x11\xba\xe2\xf2B\xe3\x1fo\xde\xda\xf0\xb5\xba\ +\xbe \x8d\xa9n\x04\xa0\xe5|\xf1c\x14\xe6\xbc\x87\xcb\ +\x0e(6\xdeZT\xc7\x05N\xb7\xb8\x0e\x93\xa9y\xa2\ +\xcaQ\x1fl\x99lxr>\xf0\x0f\x85'\x8b\xd5\xdf\ +E\xf5\xc4\x5co\xf8\xb2\xc3J\x18f\xebrj\x87b\ +\x12y\xa7\xeb\xa6?\xa8\xa7+-\xca^\xabV\x99t\ +\x15\x15\x18O\xe8\x96\x1f0\xbf=\xe6\xdeJ\x83\xe1\x9a\ +\xde_\xc9\xcd\xc7$j\xbd\xae\x8a\xea\xa5>\xb6\xec\x1d\ +\xfdl\x96\xb5\xb6\xde\xe0\x5cJ\xaa\xca\xd4k\xa2\x1f\xc0\ +\xbcnX9\x1d#{\xfc\x16\xee\xd9B\x9c\xb2\xf0\x11\ +&\x8f\xefE\x05P\xc8x\xe9\xc3\xd8\x11\xedg)`\ +\x8fO\xb6\xb91\x97=I\x16C\xe1\x9e-1\xda\xc8\ +n\xd7\xa2C\xae9\x15\xafz%\xbe\xaaW\xa1\xca+\ +/\x84\x8b1\x02uv\xb8vz_\xcc\xe1\x86U\xe1\ +\x0a\x0f\xba\x06.\xda\xdc\xb3Z\xb78\x0b\x93\xc6|\xdd\ +5w\xa8\xbek\xa2Z\xab\x00\x99\x09\xec\xa6\x82\x09\xd3\ +\xe0\xa2\xcdN\xf5B?1+\x18/\xd5yEJ\x99\ +5)\xaf>\xa9\xf7S\xc3\x5cm\xb8o\x993R\xbc\ +\x1dn\xda\xf4\xaev5&\x8b\xf5\x8c\xf7\xc3\xadS\xd4\ +mE{\xe1r\x16\xe2\xeb\x1d31?=k)\xdc\ +\xb4\xb1\xb3ZE\x0c\xc1$\xb1\xb6\xae\x9f\xfe\x10R\xca\ +,\x02\x8d?5\xaf\xc4\xbc\xf4\xf8\xb1L\x84\xabz\xb8\ +\xc0\xa0\x0d\xd0FL\x12\xb6j\x0d\xd0\xbd}\xa4\x94\xf9\ +\x8f\x99\x07\x16c.z\xd6j\x18k\x03\x04\xc8R\x1f\ +L\x0evu\xe5\xd4\x9eH)\xf3\x03gjj\xd4n\ +\xf1\xcfc\x0ez\xae\x9b\x80\xaa`\xf5w\xb5\xc2\x16L\ +\x0e\xfb\xa5\x94\x1d./\x82#\x1a\xcc\xe2\xec\xf5\x98w\ +\x9e\xcc\xd6-\xae\x85\xc1\xd6\xfd(\xa6H\x0fab\xd8\ +\xb7\xaf\x17\x95\x1b\xacM)\xcb\x823\x1a\xc4\x83I#\ +1\xdf<]\xe3U\x84\xdep\xd9_2\x10pV\xcb\ +aJ\x19\xf0\x1d\x9b\x0bw\xa1\x15\x0f\xcen\x9b\xc8@\ +\x88\x08\x0a\xc2d\xe0S\x7f\x9f\xfd\xd8\xcf\xe5!\xe9\xec\ +\x11\xb4\x8e!\xcbQ`\xbc\x91\x06\x91\xf7\xc1l\x15a\ +\x01&\x03\xf4\xc7\x19\xfd\x90R\xd6J\xe8\x98\xa6\xbd\x12\ +\x8c\xf9\xd4p\x1a\xd8\x5c\xbeo\x8bE\x04\xff\x15\xb7\xc5\ +\xa0\xc6R\xcaNTW\xc0E[\xc0\xf05\x9fa\x0e\ +y\xe8W\xd6N\x16\xff\xcco\xba\x97\x22\xfd\x80I\x00\ +5'\xa5\x8c\x8c\x97\xca\x0b\x82\xc6\xa1\xec\x0f\x14\x18\xf7\ +\x94\x99 }\xc7\xa5\xd1v\x90\xc5+\xb5\x01\xa8\xc4$\ +\x80\xbcI)\xcb\xaf@J\x99'\xe8\x03$\xe6K\x83\ +5\x13\xca\xdbD\x8b\xed\xf9\xcb@\x90\xc5P\x04\x1f\xf2\ +EJ\x195\x8f\x04\xbf@\xbf\x00P\x82\xd1\xd3\xd9\xad\ +0\x96/\xa7\x0d\xebr\xb1\xf6\xe2y\x08>\xe4\xeb\xf2\ +\x90\xe8\xbfV\xcb\x97i\xd31/<tsp$\x8b\ +\x17\xf1\x93\x81 \x0b\x03\x11t\xc8(\xdd2\x1b\x1d\x87\ ++OW\xa97\xcdz\x14\xf3\xa1!)\xc2\xc3<]\ +bX\x8c\xa0Cf\xa7\x94\x9d\xe2,\xa5L\xd9;\x1f\ +s\xa0\xe1+\xbc\x89|\xecj\xddA\xd7#\xdd\xcbG\ +\x89\xdanI\xbd/\xfe9\x8cE3\xf5\xe7\x98\x01\xea\ +\xeb\xeb&\xa89'\x0a\xb80[\xfa\xe3\xd2e\xce\x10\ +\xc4\xbe\x81\xe2\xe2\x5c\xb4\xce\xd1\xfe\xaa|\x88`\xfbF\ +\x03\x16\xbf\xf1s2;}\x81\xa6\xf6\xe5\x18\x97\xa6\xf5\ +T\xf2\xfb\xdc\xecn\x13\x0e\xa5 \xe6\x5c6\x86\x0c\xeb\ +r\xb1f\xb6\x87\x11l\xdf(6c\xf99\x0b\x8bj\ +\xcaF\xec\x9e\xa7\x06\xcd\x7f\x09\xe3\xd3\xc4/\x02^>\ +\xa4\xd1\x99\xb5\x94\xf0\x22\xe2^_\xd9\x8e\x98\x81\xbf\xb2\ +\xf1Y\xad\xf4 \x82\xec\x1b\xdd0\xa3_\xa3\xd7Z3\ +\xcb\xf2\xd4\xaf\xd2\xa6\xab\xc1\x9a\xf1\xa2@I}\xf5^\ +8\x9c\x9b\xdd\xed\xb2\xdcM\x889o\xd5\xc0\xb4\x17\x9c\ +\x8d \xfbF\xe3\xb6\x867{\xb1e\x9f(P\xbfM\ +\x8f\xd1/\x04\xe0\xee\xfc/J\xca^\xc7\x8d\xe1\xd2\x1f\ +\x17\xc4\xbc\xde\x87\xb2\xe9\xf6\xbc\x9a\x1b\x16\xe2\xc4\x8d1\ +\xdf\xe8\x8a\xc8\x10\xafoPU\xd7\x9c\xd6\x7fBOH\ +\x8bV\xfb%\x8d\xd2\xffo\xf1:\x8eB\xc2\xf3\xdc\xa4\ +\x86-\xc9A\x81\xf1\x86n\x94u\x88\x11/\xb7\xe1\x8d\ +1\xe1I\x04\xd77\x1a\xb6\xe2?>[\x84\x85'\x8b\ +\xf5\xb3\xdf77L\xd4w\xbe\x9d\xa6\xf5\xe1j,\xe3\ +3S\xb8\xd9\xdd\xf6\xc1\xee\xb6\x81\xd2\x8b\xe2cv<\ +B\x88Gp}\xf3qgk\xd1nC?\xa8\x1c(\ +\xcdQ\xe32\x92\xd5\xffl\x99\xac>\xb2d\x8cz\xf3\ +\xacG\xf5\xba\x04f\x5c\xc1\xbd-\xf6\x09S\xc7\xf3\xde\ +\xf8g\xb9\xd9\xdd\xae\xc8\xdb\x825T_sle\xb4\ +m\xc3{\x06j[\xf6*\x04\xb6\xf5\xa2\x0aX\xfe\x80\ +>\xc6\x91\x09/\xcf\xdd\xa47u\x0c\xdd\xf2\x83\xbe\xc3\ +\x0eY\xf0O\xf5\xf69C\x9a\x9dvvu\xf4\xfd\xfa\ +\xcd\xa6\xbb\xe7\x0d\xd3\x8b]\x8f\xdd\xf4\xbd\x1a\xb1'^\ +\xddP\xb0\xe3\xe7\x0e\xbdf\xa7\xb0-\xc8Z\xcd\xcd\xee\ +\xf6\xfe\x85#\xb0\x8e\xce=\xb7=\x19\x18\xd5\xbb\xad\x9d\ +\x8a\xce\x0cE`\xed\x9f\xb2D\xdd\x16\x8a\xabJ=\xaa\ +\xb9\x98}Q\x83\xba\xd3\xf2\xb2\xbb]\x99\xb7\x15k\xa9\ +\xde\xba\x12\x9f@7\x06\xe8\x1c\x0d^\xf6.\x17\x86\xd0\ +}\xc1+\xa6\x8f\xed\xd2\xdc\x8d\xdc\xecn{&\xfe\x0b\ +\xeb\xe9\xdc\x0fe\xf3\x90\x85\x00\x9d\x93\x81\xb0\xbb8\x93\ +\x0b3\xb8g\xde0\xd3\xc7\xb7\xef\xa2\x91\xdc\x98\xed\xaa\ +\xc3\xa9XS\xe7\x1d%\xd8\x22+\xc1\xe9\x96\x1eE@\ +[\xaf\x0f\xb6L\xe6\xe6\xc6\xd35\xd1\x0f\xf8\xe5\x88&\ +\xfd\xd8\x01n\x0c\x972O\xb0\xaelV\x09\xcc\xe5\x96\ +\x22\x10\xcc\xd6\xe9\x1f\xb1\x8f\xab'OWra\x02{\ +K\x0e\xf9m\x9c\xa9:\x18n\x95\xf1zn+\x84\xb1\ +\xed\xb4\xaa\xe3\x02\xd4Bh\xfd\x8eku\xfe6nL\ +\x80\xb2\x1c\xfc5\xd6\x1d\x22C\xd4\xdc\xf2#\xdc\x8c5\ +u\xba\xc0\x1a\xabS+\x81\xe9]\xed\x14\xe9\x16\x04\xb1\ +uz\x91\xa3\xdd\x16\xddn\xfbK\xcc#\xcc\x5c\x83f\ +\x9d9\x19\xc9Xcu\xf3\xbc\xdd\xd2M\xec~\x1c\x93\ +\xc5\xb7\x10D\xefug\xdc\xd3jy\xf5In\x16\xbf\ +\x15Z\xb9P\xb1q\xear\xc0\xcb\x1f7\xeaj\x81\xb5\ +\xf6\xb3F\xb1\x9c_\xbb\x02\x01\xf4N\xd4\x8ez[\xd1\ +^n\x8c\xf6`i\xaeeZp\xcf:\xb0\x94\x9bq\ +\xffa\xd7\x1c\xac\xb7_\xb4\x84\xe5\x94\xafj\x04\xd0\xbb\ +sZ\xfa\x89\xc7\x0b\xd4\x0d\x96.\x16Xe\xfc\x1fX\ +\xf4\x1a7c_Q]\x89N\xbc\xbf\xe4\xdbV1\x99\ +\x02F\xb5\x22\x11<\xefD\x15\xb9x\x81\x8eIz$\ +\xbeb\xb9?vt5\x99\x17\xde\xd9\xf8-\xd6\xddO\ +9\xb7\x8a\x18\xc2^~\xad,|\x84\xe0\xb5\x5cTw\ +\x96\x17\xe8\xcb\xff\xdd~\xb8\xc0\x80\x0fe\xf5\x8fp\xa8\ +\x08\x10\xd6\x9f\xbe\xbb\xfd\x0f\xcek98:\xe0iG\ +K;G+7#\xa4\xac\x88\xd35g\xb8\x89\xc7\xc0\ +\xa5c\xb0\x0ek\xb5\x94-\xa7\x8d\x19x\x89\xf6\xd0\x15\ +\x08\x5c\xf3\xf3;\xa7\xefO\xe2faG\xef_\xc4D\ +\xdd\x5c\x9e\xea%\xcc\xcb\x5c\x89\xb5X\xab\x13\x8ed\xf1\ +\x22vJ**Aw\x22h\xcd\xbf\x1d\xc6K\xd6A\ +A\xc5Q\xbd#0+\xb1y!\xe5#n\xcc\x96\xd2\ +\xdd\xfcqM\xda\x9a\xb5\x12\xa4.\x0c]\xd1\x15F\x22\ +hM\xeb\xd1\xa5o\xe9\x9d\x12x\x80n\xc1Q\x1d[\ +\x96\xe2C\xb5w\x1bk\xaai7^[\xfb9\xd6\xa5\ +.i8\x1a;\xdaD\x94H\xceK\xb3AJ-\xa2\ +E\xccj\x87\xdf\xe4\xbc\xcd\xdc\x98\xed\x9a\xfc\xedX\x9f\ +\xb5u\x12f\xb2d\xb69\x08Z\xc3\xb7\x93\xe8#\xd8\ +\x89\xea\x0a.\x16\xef\x9e\x92LK\xe5\xcfz#J\x8b\ +\xe2\x05*\xfe~\x836G\xb1V\x85CL\x18\xed\xe5\ +\x91=\xae@\xb0\xce\x15u\x1e\xa0\x9b:\xbc\x5c\xbd\xa5\ +2\x89\x93w\xc5\xa9WN\xed\xc9|\xec(5\x8d'\ +\xa8\x16\x07\xd6\xac\xa8\xb6Q\x82\xdb\xb1P\xbf6\x18\xc1\ +\xfa%\xcb`S\xe1N\xae\x16+\x1d\x1b<\x95\xfc\xbe\ +\xadR\xf2\x8a*K\xb8\x89\xdf\x8c\xfdIX\xbb$Y\ +\x14\xf1q\x8c1Q3C^\xa0l\x03)\xe1E\xdb\ +\xc5\x90\xa7\x86\x90y\xe5\x85X\xb7\xba\xd9\x0a\xaf\xa2X\ +8c\xa26\xe0\xb4\xdb\xb3;\xb4\xfb\xbbk\xeeP[\ +\xc6\xf0\xb3\xed\x91\x5c\xfd:\xa1,\x0c\xee?\x92)\xd2\ +\x0f,|\x1c\xdb\x0c\x93=W\xd4\xae\xdb\xde9\x9a\xa7\ +l]\x88\xfa\xb9\x94q\x5c\x99\xadU\xafP\x9bj\xb6\ +\xb2\xb8\xde\xdaN\x9b,^D\xcd\xd3`\xb0\xe7\xaa\xbd\ +\x12\xac\xae\xcd\xdfn\xdb\xc59>5\xc2\xd6\xf1\x0b\x99\ +\xff2Wf\xdb\x7f\xf1h\xac[\xbaI\x16\x1az\xa1\ +e\xbd\xb6\x9d,\xfe\x19A\xf2\x9c\xf6\x95Y\x96g\xbb\ +\x85I5\x0e\xa8\xf3\xaf\x9dcwG\xdcS\x5c\x99\xad\ +?Z\xc9[\xf3&Y\xd0\xf5V.>\xd3\x0fAj\ +\xfc2CF\xa9\xbd\x0c\xf7\xed\x8d\xdf\xd8>nt\xf3\ +\xcd\xee\x19$9'\x0a\xd4\x1f\x8f\xee\xd3\xebAt\x9c\ +\xda\x1d\xebU?\xb7\x15\x1f\xb0\xae\xd9*\xd2\xeb\x08R\ +\xe3\xfas\xcc\x00u\xd3\x91t\xdb,\xd4[c\x07\xdb\ +>f\xb7\xc5>\xc1L<(\x97;[3N\xaa\xb7\ +A\xc6I]'\xc2v\xc6\xaa\x1f\xa7\xca\xea\xe8\xf5_\ +\xaa\xc3V~\xa0\xf6K\x1a\xa5\xe7~\xd3\x1f\x11;\xe4\ +BsymW3\xdb\x89\x08P\xf3\xf2o\xbfJ\x9b\ +\xce|\x09?\xba\x09\xc7\xea5\xdc\x96\x88\x8a\xe7\x98\xcd\ +\xa93\xd5j~E\x91\x9aZ\xb4G]\x94\xbdV\xcf\ +\x7f\x9d\xa4\x99\xe6'\xdb\xdc\xea[\x1b\xbe\xd6\xdb\xae\x93\ +iR\x06\x08\xfd\x01\x87i\x1ab\xb6_X9\x13!\ +\x1e\x01j\xbe\x84\x84\xe7\xd5U\x87S\x995[\xdaA\ +\xf1\x10\xa7w[ye\xf7\xe4\xe9J=\x7f5\xfd\xd8\ +\x01=\xde\xf1\x99)\xaa\xb2w\xbe~u\xfb\xfd\xcd\x93\ +\xd4W\xd7\xfcW}b\xf9{j\x9f\x85\xc3\xd5\xaes\ +\x9f\xd1\xcd\xd3\xee\xe7\xe0\x8ch\x8e\x95\xcd6\x0d\x01\xf2\ +\xcet#\xf7.P\xcbN\x95\xfb\xd5<i\xa7}\xb8\ +\xbcH\xddR\xb8K/\xc0\xf2\x93V\xe4mQwh\ +FA\x97\x16\xea\xee\xc6\x8f\x9c,\xe6\xa2\xa8{\xda\xd1\ +\xfd\xfa\xfbV\x9d\xddm\xee*\xce\xd0\xb3K\xe6\x1fZ\ +\xa5N\xdd\x9b\xa8N\xdc1C\xfd\xcf\x96\xc9\xea\x88\xb5\ +\x9f\xeb\xb7\xe7\xa8\x87\xd9=\xf3\x86\xa9\x7f\x8d\x19h\x99\ +&\x96\x90WJ\xb5\xb2\xd9\x96!@\xde\xeb\xf7Q\xbd\ +\xd5!\xcb\xc7\xaa\xe1\xbb\xe7\xea\x1f+N\xf9\xa8\xbc\x1f\ +\xed\xac\xb2\xca\xf2\xd5\x8dGv\xa8\x89YkTyO\ +\x82\xfes\x94\xaaq=\xb6\xec\x1d=G\xf6O3\x07\ +4\xab5\x0a\xd5<%C!\xa3!\xe3\xbd*\xaa\x97\ +\xadcB\x85thG\xba\xbe M?\x03\x8d\xcbH\ +V\xa3\xf6%\xea1\xa2\x9d)\xb5\xcf\xa1\x9d/\x8d%\ +\x9d\x87\xd2\x0e\x95~\xde\x07\xcf\x7fI\xcfW\xa5z\xc5\ +\xd7M\x7f\x10\xa6\xcb\xa6\x8a-i\xb4m\xa2\xc5\xf6\x08\ +\x8eoE_\x85\xef\x8c{Z_\xbc/\xaf\xfaX\xfd\ +(5B_\xe4d\x96uE\xff\xd9\x17?F\xa9\xa1\ +\x9b\xc3\xf4E\xfft\xf2\xbf\xd5\xde\xdaO\xd2;\xe2\x9e\ +4\xb4#\x02\xfd\xec\xbd\xc7\xe6\x09\xf0\xaf\xac\xfe\xd4\x80\ +K UjqU\xa9\xbeK\xde]\x9c\xa9\x1b9\xfd\ +\x82\xf8\xe9l\x96b\xfa\xd3\xf9,\xc5\xf4\xa73\xda\xa1\ ++B\xf5?\x8e\xbd\x12_\xd5\xff@\xfet^\xdb9\ +\xba/z\x88\x19W#\xc1e\xbd\x024\x91\xe2\xed\x08\ +\x0ed7}\x996\x9d\x99\x8f\x95T\x88\x9eR\x0b\xe9\ +\xd8\x832^\xc8\xc0\xe9|8\xe6\xc0\x12\xdd\xc0\xe9\xb8\ +\xe3\xbf\xdb\x14\xdd\xc0G\xae\xfbB\xff\x03N\x06\xfe\xf0\ +\xe2\xd1?\x1b8\x0f\x1f<[$\xa5\xdb\xad\xd6k]\ +.\x0b}\x11\x1c\xc8nZ\x9c\xbd\x9e\x9b\xcb\x0ct\xdc\ +\x84\x98\x9f\x7fmW\xeac\xc5j_\xcf 8\x90\xdd\ +t\xa8\xec07f\x9b\xc3IvI\x0b\xd3\xbf\x9e\xb2\ +\xde1\x82,\xbc\x81\xc0@v\xfb`I\x85\xd0y\x81\ +.B \xee\xe7\x1f#H\xaf[\xf0\x18A\xfc\x04\xc1\ +\x81\xec$\xaa\xcd\xcb\x13Ks6 \xee\xe7\xd7G\x90\ +\x85\x8f\xac\x98\xf65\x19\xc1\x81\xec$\xca\x00\xe0\x09t\ +ih\xb0\xd4\xe2$+\x9am\x1c\x0f\x83\xffP\xd2\xeb\ +\xfa\x97\xdde\xb9\x9b\xf4\xab\x94\x901\xa2vB\x0b\xb3\ +\xd6\xa8\x13~\x9c\xa6\xdf\xe3\xf7G\xac\xe9\xdf\xe6\x89o\ +\xd2c`\xb0\xf55\xdb\x8af\x9bb\xe7A\xa7\xa4t\ +\xca\x83\x04\xe6C\xe7\xa6TL\xa5\x9d\x12dj\xcc\xe9\ +\x02\x08O\x84n\xf9\x01\xe6Z_\xc9V\xccFH\xb7\ +\xf3\xa0G\xef_\x04\xd7\xf33\x9fnSL\x8d\xf9\xc1\ +\xd2\x5c\xae\xc6\x97j4\xc0\x5c\xeb\xe9G+\x9a\xed!\ +\xbb\x0ex\x979C\xb8\xfa*mU\xa8\xfd\x0e\xd5\x1b\ +0#\xe6TE\xebL\x0d_1\xa7\xdbi0\xd7z\ +\xca\xb0\xe21B\xbe]\x07|\xcc\x86\x89p:\x8b\xf0\ +\xce\xc6oM\xab\x89\xc0\x1b!\x0b\xfe\x09s\xad'!\ +\xd7\x8af{\xcc\xae\x03N\x1f\x0e\x805\xa0\xe3\x1c3\ +b\xfe|\xca\x87\xdc\x8d-\x0f\x85\xe0\xbdP\x91\x15\xcd\ +\xf6\x84]\x07\x9c\xce\x0a\x815\x98\x93\x91lJ\xcc?\ +\xdf>\x95\xbb\xb1\xfd\x83\x81E\x8b\x18V\xa9\x15\xcd\xb6\ +\x1a\x95\x9f\x80\xd1|\xbfs\xb6)1O8\x94\xc2\xd9\ +yx\x15\x8c\xb5\xe1c\x84*k9mh\xe8\x85v\ +\x1ep\xaaI\xca\xdb\xc7\x12\xabB\xb5t\xcd\x88\xf9\xbe\ +\xe3\xd9\x5c\x8dkn\xf9\x11\x18k\xc3\xaaq\xa8\x8e\x0b\ +,\xe3\xb5\x9de\xf1\xd7v\x1f\xf4%9\xeb\xe1t~\ +\x86\x8a\xc2\x98\xd1.\x86\xea\x08\xb3\xde\x1f\xae\xa5l?\ +\x8a\xba\x08\x9e\xe4\x88\x19x\x89e\xcc60\xaaw[\ +\xbb\x0f\xf8\x1dqO\xa9%Uep<?A\xed\xb6\ +\xa9 \xba\x19\xb1\xa6\x82\xe8\xbcA](`\xac\x0d\xab\ +\xfd\x94{\xda\xc0lM\x16U\xc6\xa7k\xba\xd55\xa7\ +\xe1~&A\x1d\x0d\xe6e\xae\xd4\x1b!\x9a\x15gj\ +o\xc3\x1b3\x0f,\x86\xb1\xb2`\xb6<\x1c#\xd4\xd5\ +\xd6\xa2\xddpA\x93\x18\x9f\x1a\x81\xec\x13\x13\xf8\x16u\ +\x11\xd88F\xb0\xfb\x07\xb2\xf3EmF\x809P&\ +\x88\xd9\xf1\x9d\x9b\xb9\x82\xbbq\xa6\xee\xc00V\x06>\ +\x90\x9dM\xfd:\xc5K\x00\xa8\xf1\x220\x07\xea\x8fe\ +v|\xf7\x94dr7\xce\xc3\xd7|\x06ce\x22\xf5\ +\xcb\xe6\x97\x1a\xce\xd73+B\xe1\x82&A\x1f&\xcd\ +\x8c-e;\xf8\xaa\x85<K<\x8e\xba\x08L]j\ +8\xc6K\x00\xee\x8d\x7f\x16.h\x12WE\xf52\xfd\ +#(\x8ft_\xf0\x0a\x8c\xb5a\x15Z\xaf\x07\x99[\ +<\xccK\x00x\xac\x08\xe5\xafL\x04\xb3c;\x94\xd3\ +_-\xb7\xc5>\x01ce\xa7\x10\x8d}K,6\xa4\ +\xac\xb2|\xb8\xa1\xc1\xec8v\xc0\xf4\xb8~\x9c*s\ +9\xd6WG\xdf\x0fcmX\x07Q<\xdc\xcf\xa2|\ +[`,\x8b\xb3\xd7\x9b\x1e\xd7\xd8\x8c\xe5\xdc\x8d3\xd5\ +\x09\x86\xa9\xb2U<|%OA\xa06-\xc0X\x22\ +\xf6\xc4\x9b\x1e\xd7\x9d\xc5\x07\xb9\x1b\xe7\xbc\xf2B\x98\xaa\ +g-\xb7\x9e\xd9*B,OA\x18\xbd\xfeK\xb8\xa1\ +\xc1|\xb8u\x8a\xb97\x85\x94`\xb5\x8a\xc3L\x84\x1f\ +\x8f\xee\x83\xa9z\xea\xae\xabH1\x963[\xed\xa1~\ +\xe0)\x08\xfd\x92F\xc1\x0d\x0d\xe6\xe5U\x1f\x9b^\xff\ +\x82G\xe8H\x0c\xc6\xda\xb0\x9cn\xf1{\x0bf#H\ +\xe3y\x0a\xc2M\xb3\x1e\x85\x1b\x1a\xcc\x83I#M\x8d\ +\xe9\x93\xc9c\xb9\x1cg\xba\x11\x09c\xf5\xa8qV\xcc\ +\xb3\x1d\xc5\xd5\xcf\x0b\xb7\xa4\x9e\xa8\xae\x80#\x1a\x085\ +\xda43\xa6tl\xc1#\xdf\xa5\xcf\x82\xa9z\x92,\ +\xbef=\xb3\x95\xc5\xa1\xbc\x05\x82j\x80\x02\xe3\xa0|\ +f3\xe39\xeb\xc0R.\xc7\xf9\x03\xd4Eh\xc4l\ +\x85'\xadwf+\x0b}y\x0bD\xec\xc1epD\ +\x838Zy\xdc\xf4x\xa6\x1d\xdd\xcf\xe5X\x8fX\xfb\ +9L\xd5\xd3/XY\xeac\xbd3\xdb\x88\xa0\xdbx\ +\x0b\xc4'\xdb\xdcpE\x9b|!o\xa7\x04\xe9}\xb8\ +xd\xf0\xb2wa\xac\x9e4E\xba\xc5rf\xdb6\ +\xbcg o\x81xv\xe58\xb8\xa2A,\xccZc\ +j,\xe9|\x98Wz$\xa2.\x82'Qc\x04\x87\ +\x15\xd1\x1e\xae\x84\xa7@\x08\x09\xcf\xc3\x15\x0db\xca\xee\ +\xb9\xa6\xc6\x92vw\xf8\x10\x09\x9dW\x17\xe1\xa8\xc3\xaa\ +\xb8\x14q\x1bO\xc1\xa0\x8aT5*\x0a\xd2\x18\x81\xd9\ +\xc5\xac\xe9\xdf\xe3\x95k\xa2\x1f\x80\xb16l\xb6[\xac\ +k\xb6\xb28\x97\xb7\x80P\x0bh\xe0{^\x5c5\xde\ +\xd48\xce\xd8\x9f\xc4\xe58\xd3\x8d9\x98\xaaG\xcd\xb6\ +\xb2\xd9~\xc9[@V\xe4m\x813\x1a\xc0\x03\x8b^\ +35\x8e\xa9E{\xb8\x1c\xe7\xc3\xe5E0U\xcf\xfa\ +\xdc\xcaf\xfb\x1ao\x01\x09\xdf=\x17\xceh\x00\xb7\xc6\ +\x0e6\xef#\x88\x22\xe9\xad\xd2y\x84\xd2\xdd`\xaa\x9e\ +..\x89\xafX\xd9l\xfb\xf1\x16\x901\x1b&\xc2\x19\ +}\x0c\x9d\x83w\x9c\xda\xdd\xb4\x18\xfe#\xf6qn\xc7\ +z9\xea\x224R\x84F|\xc0\xb2f\xdbV\xeev\ +\x03o\x01\x19\xb0\xf8\x0d\xb8\xa3\x8f9r\xb2\xd8\xd4\x18\ +\x0eZ\xfa6\xb7cM\xb7\xe6`\xac\x1e\xaf\xeav\xb6\ +\xac\xd9\x9emi~\x82\xa7\x80\xfcm\xf6 \xb8\xa3\x8f\ +\xd9V\xb4\xd7\xd4\x18\xfe{\xf3$n\xc7\xfa\xfb\x9d\xb3\ +a\xaa\x0dg\x22\x1c\xb7\x5c\x0b\xf3\x06\x8a\x88o\xe0*\ +\xe9\x99\xe3\xf3>\xa3X\x90\xb5\xda\xd4\x18N\xdb\xb7\x90\ +\xdb\xb1\x1e\xb75\x1c\xc6\xda\x90\x14a\x8d\xc3\xeah\x0f\ +:\x99\xb7\xc0P\xaf,\xe0;~\xd85\xc7\xd4\xf8m\ +.\xdc\xc5\xedX\xbf\x86\xba\x08\xec\xd4\xb1\xado\xb6\xd2\ +p\xde\x02\x13\x97\x91\x0c\x87\xf4!\xa1\x9b\xc3P*\xd3\ +$\x9eX\xfe\x1e\xcc\xb5\xe1\x0e\x0d\xff\xb4\xbe\xd9\xca\xa2\ +\xc8[`>\xdb\x1e\x09\x87\xf4!\xcf\xa5\x8c\xc3\x99\xbb\ +I\xf4L\xfc\x17\xcc\xb5\xc1j_\xc2}\x967[\x1e\ +\x0b\xd2\xbc\x90\xf2\x11\x1c\xd2\x87\xf4^8\xdc\xb4\xd8=\ +\xb2d\x0c\xd7c};\xea\x224\xa4\x9a\x80\xb0\x10\xa7\ +\x83\x05\xb4\x87\xcd\xe1)8A\xf3_\x82C\xfa\x90[\ +f?nZ\xec\xde\xdb\xf4\x1d\xd7c\xdd9\xba/\xcc\ +\xb5~&\xc2!\x07+\x04\xc8\xe2\x0c\x9e\x82\xd3iZ\ +\x1f\x14\xa4\xf1\x11gjj\xd4+\x22CL\x8b]\xe4\ +\xde\x05\xdc\x8e\xf5\xa93\xd5\xfa\x995\xcc\xf5\xbc\x8fc\ +\x8a0\x8d\x19\xb3u\xc9\xc2\xab\xbc\x05(\xbf\xa2\x08N\ +\xe9\x03\x0a*\x8e\x9a\x1a\xb7\x8dGvp;\xd64g\ +a\xae\x8c~\x1c\xe3\xb9k\xc3\xaa\xc3\xa9pJ\x1f\xb0\ +\xa5p\x97\xa9\x99\x08\xa5\xa7\xca\xb9\x1dkJY\x84\xb9\ +2\xd2\x9d\xc1#1\x03\x7f\xa5=t)O\x01\x8a\xd8\ +\x13\x0f\xa7\xf4\x01\x09\x87RL\x8b\xd9_c\x06r=\ +\xd6T\xb1\x0e\xe6ZO%t\x13\xd6\xc1\x12\xdaC/\ +\xe5)H\xefl\xfc\x16N\xe9\x03&\xed\x8c5-f\ +\xfd\x17\x8f\xe6z\xacg\x1fD]\x84\xfa)_\xe2\x22\ +\x07k\xb8\xdc\xc2\x7fx\x0a\xd2\xc0\xa5c\xe0\x94>\xe0\ +\xfd\xcd\x93L\x8b\xd9\xdb\x1b\xbf\xc1\x1f6\x18\xec\xf9\xad\ +\xcb\xc72g\xb6\x01\x8a\xd0\x9b\xa7 \xf1\x5c\xa6\xcf\x97\ +\x0c[\xf9\x01\xb7G?\x85'\x8bM\xfd\xf7>J\x8d\ +\x80\xb9\xd6\xcbD\x10C\x983\xdb\x8e\x91=~\xab=\ +|%O\x05ixm\x85\xedK\xcc\xbc\xd1\xb4\xae\xe0\ +G\xcb\xbcw\xe5\xe9S\xea}\xf1\xcf\xe9mj\xccb\ +\xe4\xda\xff\xc1`\xcf\xcd\xaf-\xef,\x8b\xbfv\xb0\x88\ +\xf6\x02Kx\x0a\xd6\xae\xe2\x0c\xb8e+\xb9y\xd6\xa3\ +\xa6\xc5\xab\xb8\xaa\xd42\xef\xfd\xbf\x1f\xa3LOE{\ +2y,\x0c\xf6\xdc\xe23\x89\x0eV\xd1^`\x14O\ +\xc1\x8a\xcfL\x81[\xb6\x82\xd35g\xd4\xf6J\xb0)\ +\xb1\xfa\xd3\xcc\x01\x96y\xef\x83\xa5\xb9\xea\x95S{\xea\ +\xcf5\xe1\xc7i\xa6\xfd\xbb\xbd\x12_\x85\xc9\x9e#i\ +8\xb3f\x1b\x18\x11\xfcW\x9e\x82\xf5\x85\xb6;\x01\xde\ +cf\xf3\xc1\x87\x92^\xb7\xcc{SV\x84?>\xb4\ +\xde\x11\xf7$\x0c\xb6\x8e\xda(\xc17:X\xc6\xa5\x88\ +\x99\xbc\x04\xeb\xe5U\x1f\xc31[\xc1\xa6\xc2\x9d\xa6\xc5\ +\xeaM\x8b\xf4\x8e\x8b\xcdX~\xces\xfdaZ\x1f}\ +\x87o\x06\xd7NG]\x84:\xda\xef`\x9d\x00\xb7\x10\ +\xc6K\xc0B\xe6\xbf\x0c\xc7l\x05s3W\x98\x16\xab\ +)\x16\xe8\x8a\x5cRU\xa6\xde8\xb3\xbf_\xda\xaa\xa3\ +.\xc2y\xe7\xb5\xb2\xf0-\xf3f\xebR\x84\x87y\x09\ +\xd85\xd1\x0f\xc01[\xc1w\xe9\xb3\xb8\xba^My\ +\xbe\x0d=\x1b\xf5\x053\x1a\xb3kP0P\xbf\xb6/\ +\xfb;\xdb\xb0\x10'O)`GL\xce\x95\xb4\x13\xef\ +n\xfc\xd6\xb48\x1d\xad<\xee\xd7w\xa5\xac\x03J\x17\ +l\xe8\xd9\xa8{\x82\xd1\xa4\xa3.B\xdd,\x84\x93\x1d\ +b\xc4\xcb\x1dv@{\xa18^\x02\xb76\x7f;\x5c\ +\xd3K\x86\xae\x085%F\x7f\x9c\xd1\xcf\xefY\x17T\ +\x03\xb9\xb1\xe73\xbad\xe7\xca\xbc\xad0\xda_4\xcb\ +a\x17\x02di0/\x81S\xf6\xce\x87kzI\xf7\ +\x05\xaf\x98\x12\xa3\xbe\x8bF\xfa\xf5=\xbfM\x8fi\xf2\ +\x19\xd3\x0dn\x22\x1a{p\x19L\xf6\x97\xf3\xda\x81\xb6\ +1[\xda\xa2k/U\xc1C\xe0\xc6n\xfa\x1e\xae\xe9\ +%T\x85\xcb\x8c\x18\x8d^\xff\xa5\xdf\xde\xf1P\xd9a\ +\xf5wQ=\x9b|\xc6\xc9\xbb\xe2\x0c}\x0e\xd4E\xf8\ +YeW\x85\xf5\xfd\x8d\xc3N\xb8\x14!\x96\x87\xe0\x0d\ +Z\xfa6\x5c\xd3\x0b\xaakN\xab\xed\x94 Sb\x14\ +\xee\xc7L\x84\xe6v\xb3}fE\xa8\xa1\xcf\xf1\xe1\xd6\ +)0\xda\xda*_3\x1cv\xc3\xa9\x88\x83x\x08^\ +\x979C\xe0\x9c^\x90s\xa2\xc0\xb4\x18\xad\xce\xdf\xe6\ +\x97w\x5c\x90\xb5\xba\xd9\xcfH)aF\xf2\xda\xda\xcf\ +a\xb6\xfa\xc71i\x80\xed\xcc\x96\xb6\xea\xda\xcb\x9d\xb0\ +{\xf0\xe8\xba\xa9\x99\xc5D\xec\x02}\x9d7+FE\ +\x95%\xa6\xbf\xdf\x89\xea\x0a\xf5\xa6\x16\xd6}\xd8w<\ +\xdb\xb0\xe7\x19\xb2\x1cu\x11\x5cn\xe18\xb3\x85g\x9a\ +\x91\x950\x9b\x87 \xee-9\x04\xf7l!s2\x92\ +M\x89\xcd\x0d~\xcaD\xa0.\xbe-}V\xf7\x9e\x04\ +\xc3\x9e\xc7\xcc\xeaj\x16N\xf9\x9a\xee\xb0+m#\xa5\ +\x9e<\x04\x91~.\x82\x96\xf1\xf5\x8e\x99\xa6\xc4\xe6\x81\ +E\xaf\x99\xfen\xdb\x8f\xee\xf5\xaa\xc0\xce\x0b)\x1f\x19\ +\xf6Lt\xdc\xc5\xbd\xd9F\x04\x05\xd9\xd6l\xa9\xb7\x8f\ +\xf6\x92\x19v\x0f\xe2\x97i\xd3\xe1\x9e-\xc4\xd3m*\ +\xd63\x11\x9a\xca\xa9\xf5W\x8f\xb4\xab\xa3\xef\xe7\xddl\ +\xf79T\xc7\x05\x0e;Cm'\xec\x1e\xc8\x7f\xad\xf9\ +\x14\xee\xd9B\x9eJ~\xdf\x96\x99\x08T\x83\xa15\xcf\ +K\xa9b\xbe\x86\x0a\x95s\x9f\x85\xe0\x16\xdev\xd8\x9d\ +vJ\xd0\xef\xb5\x97=m\xe7@\xf6H|\x05\xee\xd9\ +B\x82\xbd\xdc\xfdY9\x13\x81JFR\x15\xaf\xd6<\ +\xef\xf4\xfdI>\x7f\xae\xdc\xf2#\xbc\x9b\xed\xa9\x0e\xb2\ +x\xa5\x83\x07\xb4\x97M\xb0s0\xfd}\x1d\x94E\xfe\ +\x12\xf3\x88)\xb11\xb3\xcf\x97/\xfa\xa9\xbd\xba\xe6\xbf\ +\x86\x9c!sn\xb6q\x0e^p\xb9\xa5\x07\xed\x1eP\ +\x7f\x17:a\x09*\xf7\xe7\xa9(\x0b\xab\x7f\x04\x93\xb2\ +\xd7\xf9\xe4\x99o\x8b}\xc2\xe7\xcf\xb64w#\xe7G\ +\x08\xd2\xfd\xdc\x98\xad#\xac\xcb\xc5\xdaK\xe7\xd99\xa0\ +\x1b\x0av\xc0E\x9b\x09\x9dK\xda)\x13\xe1\xe4\xe9J\ +\xf5\xd6\xd8\xc1>{n:\x8e\xf0%3\xf6'\xf1l\ +\xb69\x8ed\xf1\x22\x07O\x04\xc8\xe2[v\x0ej\xd4\ +\xbeD\xb8h3Y\x93\xbf\xdd\x94\x98\x8cZ7\xc1\x94\ +\xf7\x19\xb75\xdc\xa7\xcfMEcXL\xb3\xb3h\xd1\ +\x997\x1c\xbc\xe1\x9cvo\x00\x15\x81\xb0kPC7\ +\x87\xc1E\x9bI\xcc\x81%\xb6\xc9D\xd8]\x9c\xa9^\ +\x11\x19\xe2\xd3\xe7~\xdd\xc7\x7f$hnrj\xb6%\ +\x81Q\xbd\xdb:xD{\xf9\xaf\xed\x1a\xd8\xc1\xcb\xde\ +\x85\x8b6\x13\xea(k\x87\xee\x0cT\x83\xb6\xf7\xc2\xe1\ +>\x7f\xee\xbb\xe6\x0e\xf5\xe9sRj\x22\xa7\xdds\xbf\ +p\xf0\x8a3\xb2\xdb\xb5vM\x03\xbb#\xee)\xb8h\ +3\xa1\x9f\xf7v\xc8D\xa0\xa3#\x83>\xe8\xf8\xb4\x03\ +\x08U\xa6\xe3\xd0l\xab]\xe1A\xd78x\xc6\xae\xa5\ +\x17\xe9\xa7$\x95\x0d\x04\xd6X\xfcFg\x22\x90\x91\x1b\ +\xd9\xad6>3\x85\xb9\x9cf\x94R\xb4\x18\x81\x11A\ +w\xdb5\xc0\xfb\x0d\xac\xdad'\xee\x8d\x7f\xd6\xf0X\ +\xdc\xbfp\x84\xa1\xef\xf0\xcf\xd5\x9f\x18\xfa\xfcom\xf8\ +\xdag\xcfz\xcb\xec\xc7\xf9\xfb0\x16)\xde\xee\x00\xfa\ +\xd9\xedF;\x06xQ\xf6Z8i30rGh\ +F&\x02\xf5\xf32\xba-x\xb7\xf8\xe7}\xf6\xbcW\ +E\xf5\xe2\xcdlW\xc3em^\x0dl\xe2\x8e\x19p\ +\xd2&\xa0:\xaff\xc4\xc2\xa863Tg\xe0v\x13\ +*h\xd1\xa5\x8f\x92\xaa\xb2V?oy\xf5I\xfe\xce\ +k\x15A\x82\xcb\x9e\xb3\xbb\x15V\xda-\xc8\xc3\xd7|\ +\x067m\x02\xaa\xfd\xcbr&\xc2g\xdb#\x99\xfa\xa5\ +d\xd6\x05\x12\x0bi9\xdc\xb5\xfe\x872\xc9n\x81\xa6\ +4 \xd08\xcbr7\x99\x12\x8b#\x06d\x22\xec-\ +\xc9R;N\xedn\xda|z\x7f\xf3\xa4V?\xf3\xe6\ +\xc2]\x5c\x99-}\x13\x82\xbb6|v\xbb\xdcN\x81\ +\xbe\x01\x05i\x9a$r\xef\x02f3\x11\x1e^<\xda\ +\xd4\xf9\x142\xff\xe5V?3\xed\x8e9*\xa3\x98\x04\ +W\xe5(3\xa1\xb8\xaa\x14\x8e\xda\x08\x1f\xa7\xcaLf\ +\x22\xcc>\xb8\xd4/\xfd\xed\xcaN\x95[2\x17\xd8\x82\ +\xaaA\x06BS5\x13\xb4\xbfFv\x0a\xfa\xa6\xc2\x9d\ +p\xd4Fxe\xb5\xf1\xb7\x99|}\xdd\x95\xfe\x80\xde\ +8\xf3a\xbf\xcc\xa7\xe5\xb9\x9bZ\xf5\xec\x13\xd2\xa2y\ +1\xdb\xf9p\xd3\xa6v\xb7\x8a\xd0\x95\xfe*\xd9%\xe8\ +F\x14\x7f\xb6\x13\xfd\x92F\x19\x1e\x83\xb0\x9d\xb1>}\ +\xe677L\xf4\xdb|\x1a\x9f\x1a\xd1\xaag\xf7\xa6\xf1\ +$\x83]s\xcf`W\xdb\xfc\xcc\x04\xc5.\x81\xff`\ +\xcbd8j#\xdc\x11\xf7\xa4\xe11H9\xbc\xd5g\ +\xcfK\xa53\xcd\xa8\xbdk\xd4G\xd7\x17W\x8d\xe7a\ +W\x1b\x0e\x17m&\xbf\x9d\x1c\xdc\x91z\xba\xdb!\xf0\ +O&\x8f\x85\xa36\xc2\xef\xa2z2\x93\x89@E\xce\ +\xef\x9e7\xcc\xaf\xf3\x89\xb2\x1f*OWy\xfd\x0e\x03\ +\x16\xbfa\xfb\xca^\x97G\xf6\xb8\x02.\xda\xb2\xcc\x84\ +\xf7\xec\x10|_Wl\xb2\x13\xd4\xcd\xc2\xe8\xf1\xbf~\ +\xfaC>{\xde\xaf\xd2\xa6[bN\xb5\xa6\x8f\x9a\x90\ +\xf0\xbc\xbd\xaf\xe5\xba\xa57\xe1\x9e-\xa4\xb3,\xfe\xda\ +\x0em\xcfi'B\xed\xacA}\xcc\xe8\x85\xd5\xc7G\ +\xb9\xce\x19\xa5y\xa6\xec\xc2\x9b\xa3O\xb7)^\xbf\x07\ +\xb5G\xb7\xb1\xd9\xeeu\xc4\x0c\xbc\x04\xee\xe9\x05NE\ +\x1cd\x87I@\x0b\x15\xd4'1k\x0d3\x99\x08\x03\ +\x96\xbci\x99\xf9D\x1f\x15\xbd\xc5\xccK\x18\xa6K\x16\ +\xfb\xc15\xbdEu\x5c\xe0t\x8b\xebX\x9f\x04Kr\ +\xd6\xc3Y\x1b\x80\xea\x15\x18=\xf6?\xec\x9a\xd3\xea\xe7\ +\x9c\x97\xb9\xd2R\xf3\x89v\xd8Ug\xaa[\xfc\x1e\xc7\ +\xabN\xd89\x03a%\x0c\xb3\xb5y\xb7\x91\xe2\xcd\xda\ +@V\xb1<\x11\xbeM\x8f\x81\xb36\x80\x19\xedYZ\ +\x9b\x89@\xc5_\xfe4s\x80\xe5\xe6\xd4\xc6#-o\ +(J%?\xedyN+\x9el\xa3\x04\xdf\x08\xb7\xf4\ +I\xdd\x04\xe9\x03\x96'\xc3\xc8\xb5\xff\x83\xb36\xc0\xb3\ ++\xc7\x19>\xf6\x05\x15\xc7\x98\xcd\xa9mLt9\xc1\ +\x9b\xb45\x9b\xeel\xdf\x83K\xfa\x8a\x89\xbd/\xd5v\ +\xb7\xe9\xacN\x06\xb3Zh\xb3F\xaf\xc4W-\x9d\x89\ +\xb0\xe9H\xba_sj\x1b\xd3\xc0\xa5cZ\xfc>\xf3\ +\x0f\xad\xb2\xa3\xd1\xa6r\xd7\x9a\xdc\xf0\x9be\xb2x\x17\ +\xdd\x0caqB\xd0\xcfPP\x9f\x9bg=j\xd9L\ +\x04jit\x8f\x9fsj\x1b\xd3\x1f\xa6\xf5iq\x96\ +\x8b\xbc'\xc1nF{\xba\xad\x12t'\xdc\xd1\x88\xec\ +\x04\xb7\xf8=\xab\x13\xa3\xb4\x95\x05D\xec\x06\x19\x05\x15\ +V\xb1j&\xc2w\xe9\xb3,?\xa7R\x8b\xf6\xb4\xe8\ +\x9d\xcc\xac\xbdkNQpi\x22\x5c\xd1\xa8\xddmT\ +\xef\xb6\xda g\xb381\xb6\x16\xed\x86\xc3\xd6!\xb7\ +\xfc\x88e3\x11rN\x14\xa8\x9d\xb4\x9d\xa3\xdd>\xbc\ +\x8e\xb1\xe8\xf9\xb3\x97:\xd81\xb2\xc7o\xe1\x8aF~\ +,\x93\xc5~,N\x8e\x99\x07\x16\xc3a\xeb@_\xd3\ +\x8d\x1es\xea\x0d\xe6\x0dO,\x7f\x8f\x899E\xcfi\ +\xb5\x0f\x92\xe6u\xcb\x15\xfa\xc2\x0dM9N\x90\xbec\ +mr|\xb8u\x0a\x1c\xb6\x0es2\x92-\x99\x89\xb0\ + k53s\x8a\x1ae\x9e\xa9\xa9i\xf6\xbb=\x94\ +\xf4\xba]rj\xbf\x82\x0b\x9a{\x957\x8d\xa5\x092\ +tE(\x1c\xb6\x0e\xd4\x0c\xd3j\x99\x08\xd4|\xf2&\ +\x83?\xda\xf9Z;\x8b\x0f6\xfb\xfd\xee\xb6\xf0\x07\xbf\ +\x16\x18\xedv\xcaN\x82\x0b\x9a\x9a{\xdb\xedV\x96.\ +;\xd0\x97m`\xde\xf9\xa17\xa5\x08\xdf\xdd\xf8-s\ +\xe6\xd3\x92\xae\xc17\xce\xec\xcf\xfc\xe5\x85@\xb7t\x13\ +\xdc\xcf?\xb5\x13\xc6\xb02Q\xae\x9c\xda\xb3E?\xf9\ +\xec\xce\x90\xe5c\x8d\xbdH\xb2\xee\x8b\x16=\xcf\xb6\xa2\ +\xbdj;%\x889\x03z\xa6\x99\xbf\x98h\xee\xb1\xf8\ +~\xe7e\x1f\xbc\x0e\xd7\xf3\x17\xa1\xa1\x17\xba\x14a\x19\ ++\x93%\xab,\x1f.{\x161\xe1\x05\xcbtg\xa0\ +44)\xe1E&\x0d\x88v\xab\xcd\xa1\xa8\xb2\x84\xf5\ +]m\x22\xd5J\x81\xe9\xf9sw\x1b\xd9\xedZ-\x18\ +\xc7X\x980\xcbZ\xd9?\xcaNP\xe7a\xabd\x22\ +P\x8a\x18\xcbF\xb4\xefxv\x93\xef\xb8\xa7$\x93\xe5\ +w,\x0c\x88\x0c\xb9\x1ang\x05\xc3\x8d\x08\x0a\xd2\x02\ +Rm\xf5I3\xc9\xc7\xbd\xb0X\x85:\x0d\x04\xb8%\ +\x833\x11\x8e6\xebY\xf2\xca\x0b\xf5\xdbX,\x9b\xad\ +{OB\x93\xefI\x05\xc7\x19}\xbfS\xd4u\x1b.\ +g\xadt\xb07\xad>qF\xf9\xb8\xcb+\xab\x1c(\ +\xcd1t\x9c\xaf\x9b\xfe`\xb3\x9f\x85\xb2DX\xffB\ +O}\xc5\x9a\x22\xce\x84T;\x9c\xd3\xf2\x82\xea\xb8 \ +\xc0-\xcc\xb4\xf2\xc4\xa1<G\xa0\xeae\x0f\xad\x90\x89\ +\xb0\xd0\x84\xe2\xe5f\x88\xd2\xd5\x9a\x22|\xf7\x5c\x16\xd3\ +\xbc\x14\x18\x9bE\xe9\x10#^\xae\x05i\x87U'\x0f\ +\xb5$\x01\xaa\x1a\xbd\x7f\x91\xdf3\x11\xca\xabO\x1a^\ +\x08\xc7L\x1d*;\xdc\xe8\xfb~\xb2\xcd\xcd\xda;\xa5\ +\xe1:\xae\xc5\xa1\x22\xc2\xd4a\xd3\x92W\x0c\xdd\x92\x9e\ +8\xcf;F\x17DiN&\x82\x19\x85\xcb\xcd\xd4\xf4\ +\xfdI\x8d\xbe/\x1da1\xf4>\xc5m\xa7\x8a\x7f\x84\ +\x9b\xb1q~;\xc0\xaa\xe5\x18\xa9\xc9!\xef\xbc\xb6\xf6\ +sC\xc7xE\xde\x96F\xff\xfd\x1f\x8f\xee3\xbc\xe2\ +\x98\xd9zu\xcd\x7f\x1b}\xe7\xa7\x93\xff\xcd\xca\xd1\xc1\ +\x19\x97\x22=\x04\x17c\xcbp_\xb0\xe2d\x9a}p\ +)\xf7f\xfb\xc8\x921~\xcbD\xa0\xe4\xfe\xe0\xf9/\ +\xd9\xae\x88\xf6m\xb1O4:\xe6T\xdb\x97\x89|Z\ +E|\x0e\xee\xc5 .Y\xfc\xd2j\x93\xe9\xe3T\x99\ +{\xb3\xbdk\xeeP\xbfe\x22D\xec\x89\xb7m\xd3\xc3\ +\xc3\xe5E\x1e\xdf\xfb\xce\xb8\xa7Yx\x87\xcf\xe1Z\xac\ +B7\xcc\xdcb\x9c\x95&\xd4\xb0\x95\x1fpo\xb6F\ +\xd6\x8am,\x13\x81\xcc\xe8\xea\xe8\xfbmk\xb6\xb1\x07\ +\x97y|w\xfa#d\xed\x14/!\x96\xd6+L\x8b\ +a:\xc5t\xbd,@\x16\xd7[eRu\x8b\x7f\x9e\ +k\xa35\xba\x9dvc\xcd5\x9fK\x19g[\xa3m\ +\xac3\x05\xb5\xf81\xfa\x12I+\xaf\xe2\xae\xa5u\x0a\ +\xb7\xb2\x01\x81Qb'-\xa89V\x98XWE\xf5\ +RkT~\x0b\xd2PI@\x7f\xdc\xd2[\x9c\xbd\xde\ +\xd6FK\xa2\xe3\x99\x86\xa03l\x0b?wV\xfb)\ +\xdd\xaf\x82K\xd9\x08J%\xd1\x02\x9bg\x85\x09F-\ +ax\xc5h\xd3k(\x13\xe1\xe4\xe9J\xfd\x03\x92\xdd\ +\xcd\x96v\xafGN\x16\xd7{\xff\x1d\xc7\x0eX5\xf3\ + \xd7\xe9\x0e\xba\x1e\xeedC\x02\x22\xc5\x9b\xb5 \x17\ +\xf9{\x92%\xe7m\xe6\xd6l\x8d\xfe@\x95_Q\xff\ +#\x11u\xc9\xb0\xbb\xd1\xfe\xa4\xf8\xcc\x94z\xefO\xf3\ +\xcd\x82\xcf\x9aO9\xf1p%{g(\xfc\xc3\xdfU\ +\xc2ZR\xf0\xd9n\x8c\xdb\x1anh\x9b\x98\xf3\xd9]\ +\x9c\xa9^\x11\x19\xc2\x8d\xd9\xbe\xb5\xe1\xebzc@\xe9\ +\x86\x16\xdb\xd1\x1euM\x91n\x81\x1b\xf1p\x86\xab\x08\ +]\xb5\xa0\x97\xf9k\xb2\xbd\xb9a\x22\xb7f\xfb\xd2\xaa\ +\xf1\x86\x8dk\xaf\xc4W\xcf\xf9\xb7\xe8l\xbc7#\xf9\ +\xa5F~\x80\xfd~\xe7l+=ci\xa0,\xde\x05\ +\x17\xe2\x08\xa7[\x0a\xa66\x1b\xfe\x98p\xfd\x17\x8f\xe6\ +\xd6l\x1fX\xf4\x9ai\x99\x08S\xf7&re\xb4\xa4\ +@ERK\xaa\xcaL\xfb5\xd1\xd2\xb66T\x0e\x15\ +\xee\xc3\xe3\x91\x82\x22<\xec\x8f>f\x7f\x9b=\x88[\ +\xb3\xbd5v\xb0)\x99\x08\xf4\xa1\x88\x8e\x15x3[\ +RR\xf6\xbas\xc6|\x84\xc1\xd7\xa3\x9bytP\x85\ +k\xb8\xbc\x1bn\xa4$\x98}\xa4@\xbb\x8f\x8a\xeaJ\ +\xee\x8c\x96~\xd6w\x9c\xda\xdd\xb0qM8\xf4\xcb\xc7\ +\xa1\xe1k>\xe3\xd2hITd\xa7.O,\x7f\xcf\ +\xefG\x07.wP7\xb8\x0d\xa0,\x85{\xb5\xbf\xbc\ +\xc7\xcd\x9c\x80iG\xf7sg\xb6\x05\x15\xc7\x0c\x1d\xd3\ +\xbe\x8bF\xea\xad\x87\xc6\xa7FX:\x89\xdf\x8cR\x9e\ +Ks6\xe8\xedr\x16d\xad\xd6\xdb\xba\xfb\xf1yJ\ +\xb4X\xdc\x03\x97\x01u\xcfp\xbb\x98\x99\x166'#\ +\x99;\xb3\xddR\xb8\x8b[\x03\xe4T\x85\xce\x88\xa0\xdb\ +\xe0.\xc0SZ\xd8\x11\xb3\xaa\xebS\x87Y\x9e\xd4e\ +\xce\x10\x18\x10?\xca\x0b\x8c\x08\xfe+\x5c\x054\xf2\xd1\ +\xac\xdb\xadN\xb7x\x18\x8b\x05\x82\xbc\xbf\x19\x16\xa0\x04\ +\xff\x1dn\x02\x9a\xa4\xfd\xd4\xfb~\xa7M\x9a\xcdX4\ +\x10\xd4bm\xec \x8bW\xc2E@\xb3\xa1\xfeG\xda\ +\xc4\x89\xc7\xe2\x81\xa0fJ\x16\xe7\xa2o\x18\xf0\x8e\x98\ +\x81\xbfr)\xd2D,$\x08j\xd2hC\xa9\xc35\ +L\x03\xb4\xf2\x1cW\x1c\xa1M\xa8\xd3XT\x10TO\ +\xd5NYx\x1e.\x01|\x99\x1a\xf6\xa86\xb1N`\ +qA\xd0\xcf*s\xc9R\x7f\xb8\x03\xf09m\xe5n\ +7h\x13l\x07\x16\x19\x04\x89ih7\x0e\x0c\xa5C\ +\x8cx\xb96\xd1fc\xb1A\xbc*@\x91bh\x1d\ +\xc0\x0d\x80\xf1\xa8\x8e\x0b\x9c\x8a8\x06\xe7\xb8\x10o\xe7\ +\xb3\xf4\xfd\x02\x1f\xc2\x80\xe9\x04\xcab/\x7f\x17\x22\x87\ + \x93.*\x14P\xd1&\xacz\xe0\xe7s\x5ca\x03\ +\x16#dWQ\xf7[gD\xc8uX\xed\xc0\xff\x84\ +\x86^X\x9b\x1ef~m\x5c\x082\xb6\x06-\x8e\x0d\ +\x80%w\xb9\xc2\x1d\xda\x04\xdd\x83E\x0a\xb1\xff\x11L\ +\xdcM\x95\xf0\xb0\xaa\x81e\xe9\x14\xd3\xf52\xcdp\xbf\ +\xc2\x82\x85\x18\xde\xd1~E\xf3\x18\xab\x190A\x80[\ +x\x9c\xeayb\xe1B,}\x04\xa3\xcb;X\xbd\x80\ +=\xc3\x0d\x0bqj\xa6\x1b\xa6M\xe4\x1a,d\xc8\xc2\ +&{\x86v\xb34_\xb1j\x01\xdb\xa6+\x0b\xf7\xd1\ +\x19\x18\x165d\xc1L\x83]\xd4\x16\x0a\xab\x14\xd8\xea\ +,7@\x16?\xc1E\x08\xc82\x99\x06\xb2\x18\xdaY\ +\x16\x7f\x8d\xd5\x09lz\x96+\xdd\xa3M\xf6T,v\ +\xc8\x8f\xda\x1c(\x8bwa5\x02\xfbC\xd7}ea\ +\xa0K\x113\xb1\xf0!\x13\x95\x11 \x0b}\xb1\x00\x01\ +w\x5c\x15\xd6\xf77gk,\x94\xc1\x08 \x03UJ\ +\xf3\x0c\xe9\x5c\x80{\xda)A\xbfw)R$\xb2\x16\ + _g\x19P6L\xfb)\xdd\xaf\xc2*\x03\xa0\x0e\ +T\xe8C[$\xaba\x12\x90\x0f\x8cv%\xb2\x0c\x00\ +h\xdeG\xb4\xe50\x0c\xa8\xc5R\x84e\x81\x8a\xd0\x15\ +\xab\x08\x80\x16\xe0T\xc4\x10j\x0d\x0d\x13\x81\xb0\x93\x05\ +\xc0hBC/\x0c\x90\xa5\xc1\xdabJ\x87\xa1@\x0d\ +\xb5\xa7\xd1\xfe(\x0f\xa2y\x82\xc5\x02\x80\xaf\x8e\x17\xb4\ +\x9d\x8b\xb6\xb8\x12\xf0!\x8d{Q\xfc\x13\xb0\x93\x05\xc0\ +`\xce\x16,\xff\xca\xe9\x16O\xc2x\xb8R\x05\xc5\x1d\ +\x8d\x16\x010\x19\x97,v\xae-\xe7(\x1c\x87\x11\xd9\ +Z%\x9a&\xb8\xc2\x83\xae\xc1\xac\x07\xc0\x9fL\xec}\ +\xa9~#\xcd-.\xc1\x11\x83\xad\x8e\x0a\x96P\x5c\x1d\ +1\x03/\xc1$\x07\xc0\x82G\x0c\xb5\x05o\x84\x02\x18\ +\x16\x93\xca\xa2\x0218*\x00\x80\x11j;FHO\ +\x9d\xdd\xedV\xc3\xc4\xac\xdd\x22<\xc0-$\x05(\xe2\ +\x10T\xe1\x02\x80a\xa8\x06\x03\x15 9{%\xf8\x04\ +\xcc\xcd\x12:A\xf1\xa0\xb8P|0K\x01\xb0\x19m\ +\x94\xe0vNE|\x8evR\xd8\xf1\x9a\xaeSN\xb7\ +\xb8\xd0%K\xc3\xda\x86\xf7\x0c\xc4l\x04\x80\xa3\xa3\x86\ +\xda[j\xc2W(\xf7h`'\x04Y\xfc\x84\xc6\x19\ +U\xb7\x00\x00:\xce\x88\x90\xeb4\xd3\x1dQ{\xce+\ +T\xc1,\xbdR%]8p\xba\xa5\x17h<1\xab\ +\x00\x00M\x1e7\xb8\xdc\xd2\x83\x01n\xe1S\xcd<V\ +\xe1\x02\x85\xc7\x9d+\x8dK\x8a\xb6s\xfd\x98\xce_q\ +<\x00\x00h\x1d\x13{_\x1a\x18\x11t\xb7f.\xa3\ +]\xb28W\xdb\xf9\xe6rZ\xf0\x85\xde;N\xd3(\ +\xbd\xba\x16r`\x01\x00F\xd3~\xca=m\xb4\x9f\xcb\ +]jS\xcc\xe8&\x9b^\x8b\xd7.]'\xcaj\xdf\ +\x87\xdeKz\x8a\xde\x93\xde\x17Q\x07\x00X\x83\xb0.\ +\x17\x07(\xc1\x7f\xd7\xcci\x00\xed\xfe4}\xe3T\x84\ +\x05g\xab\x96UX\xb0\xd6\x00=\xd7|M_\xbb\x14\ +\xe9u\x97,\xf5\x0f\x90\xbb\xfd\x8d\xde\x03\xc1\x04\x000\ +K\x07Y\xbc\x92~~\xeby\xbf\xb28\x94\x0c\x99\xce\ +;\xb5\xff\x19~\xf6\xe7yJ\xad\x01\x0a\x07j%\x16\ +j:\xe6\xb9\xfe\x83\xfe\x9f\x1f\xab\xfd\xdf\xfb\xe9\xbf\xa3\ +\xff\xf7Wj\xff\xd9\x1cM\x935\xe3\x1f\xaf\x1b\xbf\xf6\ +\xef\xd1\xbfK\x9de\xe99\x10\x0d\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x8c\xe0\xff\x01/\x9b\xa0\xe9\xec\ +0\x8e\x92\x00\x00\x00\x00IEND\xaeB`\x82\ +" + +qt_resource_name = b"\ +\x00\x06\ +\x07\x03}\xc3\ +\x00i\ +\x00m\x00a\x00g\x00e\x00s\ +\x00\x09\ +\x08\x97\x8a'\ +\x00h\ +\x00e\x00a\x00r\x00t\x00.\x00p\x00n\x00g\ +\x00\x07\ +\x08wW\x87\ +\x00b\ +\x00a\x00d\x00.\x00p\x00n\x00g\ +\x00\x09\ +\x08\x9b\xa0G\ +\x00t\ +\x00r\x00a\x00s\x00h\x00.\x00p\x00n\x00g\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00*\x00\x00\x00\x00\x00\x01\x00\x00d\xb8\ +\x00\x00\x01r\x0e\xc2\x8cT\ +\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01r\x0e\xc2\x8cW\ +\x00\x00\x00>\x00\x00\x00\x00\x00\x01\x00\x00n|\ +\x00\x00\x01r\x0e\xc2\x8cW\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/examples/widgets/systray/systray.pyproject b/examples/widgets/systray/systray.pyproject new file mode 100644 index 000000000..eadfb0d7a --- /dev/null +++ b/examples/widgets/systray/systray.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["main.py", "window.py", "systray.qrc"] +} diff --git a/examples/widgets/systray/systray.qrc b/examples/widgets/systray/systray.qrc new file mode 100644 index 000000000..a8b653584 --- /dev/null +++ b/examples/widgets/systray/systray.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> + <file>images/bad.png</file> + <file>images/heart.png</file> + <file>images/trash.png</file> +</qresource> +</RCC> diff --git a/examples/widgets/systray/window.py b/examples/widgets/systray/window.py new file mode 100644 index 000000000..ca65f04e1 --- /dev/null +++ b/examples/widgets/systray/window.py @@ -0,0 +1,273 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +from PySide2.QtCore import Slot +from PySide2.QtGui import QIcon +from PySide2.QtWidgets import (QAction, QCheckBox, QComboBox, QDialog, + QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QLineEdit, QMenu, QMessageBox, QPushButton, + QSpinBox, QStyle, QSystemTrayIcon, QTextEdit, + QVBoxLayout) + +import rc_systray + + +class Window(QDialog): + def __init__(self, parent=None): + super(Window, self).__init__(parent) + + self.iconGroupBox = QGroupBox() + self.iconLabel = QLabel() + self.iconComboBox = QComboBox() + self.showIconCheckBox = QCheckBox() + + self.messageGroupBox = QGroupBox() + self.typeLabel = QLabel() + self.durationLabel = QLabel() + self.durationWarningLabel = QLabel() + self.titleLabel = QLabel() + self.bodyLabel = QLabel() + + self.typeComboBox = QComboBox() + self.durationSpinBox = QSpinBox() + self.titleEdit = QLineEdit() + self.bodyEdit = QTextEdit() + self.showMessageButton = QPushButton() + + self.minimizeAction = QAction() + self.maximizeAction = QAction() + self.restoreAction = QAction() + self.quitAction = QAction() + + self.trayIcon = QSystemTrayIcon() + self.trayIconMenu = QMenu() + + self.createIconGroupBox() + self.createMessageGroupBox() + + self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width()) + + self.createActions() + self.createTrayIcon() + + self.showMessageButton.clicked.connect(self.showMessage) + self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible) + self.iconComboBox.currentIndexChanged.connect(self.setIcon) + self.trayIcon.messageClicked.connect(self.messageClicked) + self.trayIcon.activated.connect(self.iconActivated) + + self.mainLayout = QVBoxLayout() + self.mainLayout.addWidget(self.iconGroupBox) + self.mainLayout.addWidget(self.messageGroupBox) + self.setLayout(self.mainLayout) + + self.iconComboBox.setCurrentIndex(1) + self.trayIcon.show() + + self.setWindowTitle("Systray") + self.resize(400, 300) + + def setVisible(self, visible): + self.minimizeAction.setEnabled(visible) + self.maximizeAction.setEnabled(not self.isMaximized()) + self.restoreAction.setEnabled(self.isMaximized() or not visible) + super().setVisible(visible) + + def closeEvent(self, event): + if not event.spontaneous() or not self.isVisible(): + return + if self.trayIcon.isVisible(): + QMessageBox.information(self, "Systray", + "The program will keep running in the system tray. " + "To terminate the program, choose <b>Quit</b> in the context " + "menu of the system tray entry.") + self.hide() + event.ignore() + + @Slot(int) + def setIcon(self, index): + icon = self.iconComboBox.itemIcon(index) + self.trayIcon.setIcon(icon) + self.setWindowIcon(icon) + self.trayIcon.setToolTip(self.iconComboBox.itemText(index)) + + @Slot(str) + def iconActivated(self, reason): + if reason == QSystemTrayIcon.Trigger: + pass + if reason == QSystemTrayIcon.DoubleClick: + self.iconComboBox.setCurrentIndex( + (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count() + ) + if reason == QSystemTrayIcon.MiddleClick: + self.showMessage() + + @Slot() + def showMessage(self): + self.showIconCheckBox.setChecked(True) + selectedIcon = self.typeComboBox.itemData(self.typeComboBox.currentIndex()) + msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon) + + if selectedIcon == -1: # custom icon + icon = QIcon(self.iconComboBox.itemIcon(self.iconComboBox.currentIndex())) + self.trayIcon.showMessage( + self.titleEdit.text(), + self.bodyEdit.toPlainText(), + icon, + self.durationSpinBox.value() * 1000, + ) + else: + self.trayIcon.showMessage( + self.titleEdit.text(), + self.bodyEdit.toPlainText(), + msgIcon, + self.durationSpinBox.value() * 1000, + ) + + @Slot() + def messageClicked(self): + QMessageBox.information(None, "Systray", + "Sorry, I already gave what help I could.\n" + "Maybe you should try asking a human?") + + def createIconGroupBox(self): + self.iconGroupBox = QGroupBox("Tray Icon") + + self.iconLabel = QLabel("Icon:") + + self.iconComboBox = QComboBox() + self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad") + self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart") + self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash") + + self.showIconCheckBox = QCheckBox("Show icon") + self.showIconCheckBox.setChecked(True) + + iconLayout = QHBoxLayout() + iconLayout.addWidget(self.iconLabel) + iconLayout.addWidget(self.iconComboBox) + iconLayout.addStretch() + iconLayout.addWidget(self.showIconCheckBox) + self.iconGroupBox.setLayout(iconLayout) + + def createMessageGroupBox(self): + self.messageGroupBox = QGroupBox("Balloon Message") + + self.typeLabel = QLabel("Type:") + + self.typeComboBox = QComboBox() + self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon) + self.typeComboBox.addItem( + self.style().standardIcon(QStyle.SP_MessageBoxInformation), + "Information", + QSystemTrayIcon.Information, + ) + self.typeComboBox.addItem( + self.style().standardIcon(QStyle.SP_MessageBoxWarning), + "Warning", + QSystemTrayIcon.Warning, + ) + self.typeComboBox.addItem( + self.style().standardIcon(QStyle.SP_MessageBoxCritical), + "Critical", + QSystemTrayIcon.Critical, + ) + self.typeComboBox.addItem(QIcon(), "Custom icon", -1) + self.typeComboBox.setCurrentIndex(1) + + self.durationLabel = QLabel("Duration:") + + self.durationSpinBox = QSpinBox() + self.durationSpinBox.setRange(5, 60) + self.durationSpinBox.setSuffix(" s") + self.durationSpinBox.setValue(15) + + self.durationWarningLabel = QLabel("(some systems might ignore this hint)") + self.durationWarningLabel.setIndent(10) + + self.titleLabel = QLabel("Title:") + self.titleEdit = QLineEdit("Cannot connect to network") + self.bodyLabel = QLabel("Body:") + + self.bodyEdit = QTextEdit() + self.bodyEdit.setPlainText("Don't believe me. Honestly, I don't have a clue." + "\nClick this balloon for details.") + + self.showMessageButton = QPushButton("Show Message") + self.showMessageButton.setDefault(True) + + messageLayout = QGridLayout() + messageLayout.addWidget(self.typeLabel, 0, 0) + messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2) + messageLayout.addWidget(self.durationLabel, 1, 0) + messageLayout.addWidget(self.durationSpinBox, 1, 1) + messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3) + messageLayout.addWidget(self.titleLabel, 2, 0) + messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4) + messageLayout.addWidget(self.bodyLabel, 3, 0) + messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4) + messageLayout.addWidget(self.showMessageButton, 5, 4) + messageLayout.setColumnStretch(3, 1) + messageLayout.setRowStretch(4, 1) + self.messageGroupBox.setLayout(messageLayout) + + def createActions(self): + self.minimizeAction = QAction("Minimize", self) + self.minimizeAction.triggered.connect(self.hide) + + self.maximizeAction = QAction("Maximize", self) + self.maximizeAction.triggered.connect(self.showMaximized) + + self.restoreAction = QAction("Restore", self) + self.restoreAction.triggered.connect(self.showNormal) + + self.quitAction = QAction("Quit", self) + self.quitAction.triggered.connect(qApp.quit) + + def createTrayIcon(self): + self.trayIconMenu = QMenu(self) + self.trayIconMenu.addAction(self.minimizeAction) + self.trayIconMenu.addAction(self.maximizeAction) + self.trayIconMenu.addAction(self.restoreAction) + self.trayIconMenu.addSeparator() + self.trayIconMenu.addAction(self.quitAction) + + self.trayIcon = QSystemTrayIcon(self) + self.trayIcon.setContextMenu(self.trayIconMenu) diff --git a/sources/cmake_helpers/helpers.cmake b/sources/cmake_helpers/helpers.cmake index 81b52920c..fed96b5cd 100644 --- a/sources/cmake_helpers/helpers.cmake +++ b/sources/cmake_helpers/helpers.cmake @@ -2,7 +2,15 @@ macro(collect_essential_modules) # Collect all essential modules. # note: the order of this list is relevant for dependencies. # For instance: Qt5Printsupport must come before Qt5WebKitWidgets. -set(ALL_ESSENTIAL_MODULES Core Gui Widgets PrintSupport Sql Network Test Concurrent) +set(ALL_ESSENTIAL_MODULES + Core + Gui + Widgets + PrintSupport + Sql + Network + Test + Concurrent) if(UNIX AND NOT APPLE) list(APPEND ALL_ESSENTIAL_MODULES X11Extras) endif() @@ -16,10 +24,31 @@ endmacro() macro(collect_optional_modules) # Collect all optional modules. -set(ALL_OPTIONAL_MODULES Xml XmlPatterns Help Multimedia -MultimediaWidgets OpenGL OpenGLFunctions Positioning Location Qml Quick QuickWidgets RemoteObjects Scxml Script ScriptTools Sensors TextToSpeech Charts Svg DataVisualization) -find_package(Qt5UiTools) -if(Qt5UiTools_FOUND) +set(ALL_OPTIONAL_MODULES + Xml + XmlPatterns + Help Multimedia + MultimediaWidgets + OpenGL + OpenGLFunctions + Positioning + Location + Qml + Quick + QuickControls2 + QuickWidgets + RemoteObjects + Scxml + Script + ScriptTools + Sensors + SerialPort + TextToSpeech + Charts + Svg + DataVisualization) +find_package(Qt${QT_MAJOR_VERSION}UiTools) +if(Qt${QT_MAJOR_VERSION}UiTools_FOUND) list(APPEND ALL_OPTIONAL_MODULES UiTools) else() set(DISABLE_QtUiTools 1) @@ -31,7 +60,7 @@ endif() # If WebKit support is needed add the following elements # to the list: WebKit WebKitWidgets list(APPEND ALL_OPTIONAL_MODULES WebChannel WebEngineCore WebEngine WebEngineWidgets WebSockets) -if (Qt5Core_VERSION VERSION_GREATER 5.9.3) # Depending on fixes in Qt3D +if (Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_GREATER 5.9.3) # Depending on fixes in Qt3D list(APPEND ALL_OPTIONAL_MODULES 3DCore 3DRender 3DInput 3DLogic 3DAnimation 3DExtras) endif() endmacro() @@ -89,10 +118,10 @@ endforeach() endmacro() macro(COLLECT_MODULE_IF_FOUND shortname) - set(name "Qt5${shortname}") + set(name "Qt${QT_MAJOR_VERSION}${shortname}") set(_qt_module_name "${name}") if ("${shortname}" STREQUAL "OpenGLFunctions") - set(_qt_module_name "Qt5Gui") + set(_qt_module_name "Qt${QT_MAJOR_VERSION}Gui") endif() # Determine essential/optional/missing set(module_state "missing") @@ -122,7 +151,7 @@ macro(COLLECT_MODULE_IF_FOUND shortname) # directory, to avoid CMake looking in another path. # This will be saved in a global variable at the beginning of the modules # collection process. - string(FIND "${name}" "Qt5Core" qtcore_found) + string(FIND "${name}" "Qt${QT_MAJOR_VERSION}Core" qtcore_found) if(("${qtcore_found}" GREATER "0") OR ("${qtcore_found}" EQUAL "0")) get_filename_component(_core_abs_dir "${${_name_dir}}/../" ABSOLUTE) # Setting the absolute path where the Qt5Core was found @@ -143,6 +172,16 @@ macro(COLLECT_MODULE_IF_FOUND shortname) message(STATUS "${module_state} module ${name} found (${ARGN})${looked_in_message}") # record the shortnames for the tests list(APPEND all_module_shortnames ${shortname}) + # Build Qt 5 compatibility variables + if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + get_target_property(Qt6${shortname}_INCLUDE_DIRS Qt6::${shortname} + INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(Qt6${shortname}_PRIVATE_INCLUDE_DIRS + Qt6::${shortname}Private + INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(Qt6${shortname}_LIBRARIES Qt6::${shortname} + INTERFACE_LINK_LIBRARIES) + endif() else() if("${module_state}" STREQUAL "optional") message(STATUS "optional module ${name} skipped${looked_in_message}") diff --git a/sources/pyside2-tools b/sources/pyside2-tools -Subproject 1e8ec62d53f2c7ad579292b2948ebf3aaded420 +Subproject a8448837204faee0b457d1e2d4cbf574a281111 diff --git a/sources/pyside2/CMakeLists.txt b/sources/pyside2/CMakeLists.txt index 1efcb53ed..dc2beded0 100644 --- a/sources/pyside2/CMakeLists.txt +++ b/sources/pyside2/CMakeLists.txt @@ -6,6 +6,8 @@ cmake_policy(VERSION 3.1) # Don't ignore targets that do not exist, inside add_dependencies calls. cmake_policy(SET CMP0046 NEW) +set (QT_MAJOR_VERSION 5) + project(pysidebindings) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_helpers/ @@ -77,11 +79,11 @@ if (SHIBOKEN_PYTHON_LIMITED_API) message(STATUS "******************************************************") endif() -find_package(Qt5 5.12 REQUIRED COMPONENTS Core) -add_definitions(${Qt5Core_DEFINITIONS}) +find_package(Qt${QT_MAJOR_VERSION} 5.12 REQUIRED COMPONENTS Core) +add_definitions(${Qt${QT_MAJOR_VERSION}Core_DEFINITIONS}) find_file(GL_H "gl.h" PATH_SUFFIXES "GL") -message("result:" "${GL_H}") +message(STATUS "GL Headers path:" "${GL_H}") include(FindQt5Extra) set(XVFB_EXEC "") @@ -108,17 +110,26 @@ endif() # Force usage of the C++11 standard, without a silent fallback # to C++98 if the compiler does not support C++11. -set(CMAKE_CXX_STANDARD 11) +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + set(CMAKE_CXX_STANDARD 17) +else() + set(CMAKE_CXX_STANDARD 11) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Qt5: QT_INCLUDE_DIR does no longer exist. -# On Windows, macOS, and Linux it can be computed from Qt5Core_INCLUDE_DIRS, which contains -# a list of include directories. We take the first one. -message(STATUS "*** Qt5Core_INCLUDE_DIRS = ${Qt5Core_INCLUDE_DIRS}") -list(GET Qt5Core_INCLUDE_DIRS 0 QT_INCLUDE_DIR) +# >= Qt5: QT_INCLUDE_DIR does no longer exist. Derive from QtCore +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + get_target_property(QT_INCLUDE_DIR Qt6::Core INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(QT_INCLUDE_DIR "${QT_INCLUDE_DIR}" DIRECTORY) +else() + # On Windows, macOS, and Linux it can be computed from Qt5Core_INCLUDE_DIRS, which contains + # a list of include directories. We take the first one. + list(GET Qt5Core_INCLUDE_DIRS 0 QT_INCLUDE_DIR) +endif() +message(STATUS "*** Qt ${QT_MAJOR_VERSION}, QT_INCLUDE_DIR= ${QT_INCLUDE_DIR}") # On macOS, check if Qt is a framework build. This affects how include paths should be handled. -get_target_property(QtCore_is_framework Qt5::Core FRAMEWORK) +get_target_property(QtCore_is_framework Qt${QT_MAJOR_VERSION}::Core FRAMEWORK) if (QtCore_is_framework) # Get the path to the framework dir. @@ -151,9 +162,9 @@ compute_config_py_values(BINDING_API_VERSION) include(PySideModules) # Set default values for pyside2_global.h -set (Qt5X11Extras_FOUND "0") -set (Qt5Test_FOUND "0") -set (Qt5Widgets_FOUND "0") +set (Qt${QT_MAJOR_VERSION}X11Extras_FOUND "0") +set (Qt${QT_MAJOR_VERSION}Test_FOUND "0") +set (Qt${QT_MAJOR_VERSION}Widgets_FOUND "0") collect_essential_modules() collect_optional_modules() @@ -175,7 +186,7 @@ foreach(m ${DISABLED_MODULES}) endforeach() -string(REGEX MATCHALL "[0-9]+" qt_version_helper "${Qt5Core_VERSION}") +string(REGEX MATCHALL "[0-9]+" qt_version_helper "${Qt${QT_MAJOR_VERSION}Core_VERSION}") list(GET qt_version_helper 0 QT_VERSION_MAJOR) list(GET qt_version_helper 1 QT_VERSION_MINOR) @@ -241,8 +252,9 @@ endif() ##################################################################### add_subdirectory(libpyside) -find_package(Qt5Designer) -if(Qt5UiTools_FOUND AND Qt5Designer_FOUND) +find_package(Qt${QT_MAJOR_VERSION}Designer) +if(${QT_MAJOR_VERSION} LESS 6 AND Qt${QT_MAJOR_VERSION}UiTools_FOUND + AND Qt${QT_MAJOR_VERSION}Designer_FOUND) add_subdirectory(plugins) endif() diff --git a/sources/pyside2/PySide2/CMakeLists.txt b/sources/pyside2/PySide2/CMakeLists.txt index aa37f19bc..120bc8e52 100644 --- a/sources/pyside2/PySide2/CMakeLists.txt +++ b/sources/pyside2/PySide2/CMakeLists.txt @@ -49,10 +49,10 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/deprecated.py" file(READ "${CMAKE_CURRENT_BINARY_DIR}/pyside2_global.h" pyside2_global_contents) foreach(shortname IN LISTS all_module_shortnames) - set(name "Qt5${shortname}") + set(name "Qt${QT_MAJOR_VERSION}${shortname}") set(_qt_module_name "${name}") if ("${shortname}" STREQUAL "OpenGLFunctions") - set(_qt_module_name "Qt5Gui") + set(_qt_module_name "Qt${QT_MAJOR_VERSION}Gui") endif() HAS_QT_MODULE(${_qt_module_name}_FOUND Qt${shortname}) diff --git a/sources/pyside2/PySide2/Qt3DAnimation/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DAnimation/CMakeLists.txt index 6d90f76e8..970c9102c 100644 --- a/sources/pyside2/PySide2/Qt3DAnimation/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DAnimation/CMakeLists.txt @@ -31,11 +31,11 @@ set(Qt3DAnimation_include_dirs ${Qt3DAnimation_SOURCE_DIR} ${Qt3DAnimation_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIR} - ${Qt53DCore_INCLUDE_DIRS} - ${Qt53DRender_INCLUDE_DIRS} - ${Qt53DAnimation_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIR} + ${Qt${QT_MAJOR_VERSION}3DCore_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DRender_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DAnimation_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -44,7 +44,7 @@ set(Qt3DAnimation_include_dirs ${Qt3DAnimation_GEN_DIR}) set(Qt3DAnimation_libraries pyside2 - ${Qt53DAnimation_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DAnimation_LIBRARIES}) set(Qt3DAnimation_deps Qt3DRender) diff --git a/sources/pyside2/PySide2/Qt3DCore/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DCore/CMakeLists.txt index e28de3f05..aa40c6ec8 100644 --- a/sources/pyside2/PySide2/Qt3DCore/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DCore/CMakeLists.txt @@ -32,7 +32,7 @@ ${Qt3DCore_GEN_DIR}/qt3dcore_qtransform_wrapper.cpp # module is always needed ${Qt3DCore_GEN_DIR}/qt3dcore_module_wrapper.cpp) -if (Qt53DCore_VERSION VERSION_EQUAL 5.10.0 OR Qt53DCore_VERSION VERSION_GREATER 5.10.0) +if (Qt${QT_MAJOR_VERSION}3DCore_VERSION VERSION_EQUAL 5.10.0 OR Qt${QT_MAJOR_VERSION}3DCore_VERSION VERSION_GREATER 5.10.0) list(APPEND Qt3DCore_SRC ${Qt3DCore_GEN_DIR}/qt3dcore_qarmature_wrapper.cpp ${Qt3DCore_GEN_DIR}/qt3dcore_qjoint_wrapper.cpp @@ -46,17 +46,17 @@ set(Qt3DCore_include_dirs ${Qt3DCore_SOURCE_DIR} ${Qt3DCore_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt53DCore_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DCore_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtNetwork_GEN_DIR}) set(Qt3DCore_libraries pyside2 - ${Qt53DCore_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DCore_LIBRARIES}) set(Qt3DCore_deps QtGui QtNetwork) diff --git a/sources/pyside2/PySide2/Qt3DExtras/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DExtras/CMakeLists.txt index e581bc269..947c90bf3 100644 --- a/sources/pyside2/PySide2/Qt3DExtras/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DExtras/CMakeLists.txt @@ -36,7 +36,8 @@ ${Qt3DExtras_GEN_DIR}/qt3dextras_qt3dwindow_wrapper.cpp # module is always needed ${Qt3DExtras_GEN_DIR}/qt3dextras_module_wrapper.cpp) -if (Qt53DExtras_VERSION VERSION_EQUAL 5.10.0 OR Qt53DExtras_VERSION VERSION_GREATER 5.10.0) +if (Qt${QT_MAJOR_VERSION}3DExtras_VERSION VERSION_EQUAL 5.10.0 + OR Qt${QT_MAJOR_VERSION}3DExtras_VERSION VERSION_GREATER 5.10.0) list(APPEND Qt3DExtras_SRC ${Qt3DExtras_GEN_DIR}/qt3dextras_qabstractcameracontroller_wrapper.cpp ${Qt3DExtras_GEN_DIR}/qt3dextras_qabstractcameracontroller_inputstate_wrapper.cpp @@ -51,11 +52,11 @@ set(Qt3DExtras_include_dirs ${Qt3DExtras_SOURCE_DIR} ${Qt3DExtras_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt53DCore_INCLUDE_DIRS} - ${Qt53DRender_INCLUDE_DIRS} - ${Qt53DExtras_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DCore_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DRender_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}3DExtras_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -63,7 +64,7 @@ set(Qt3DExtras_include_dirs ${Qt3DRender_GEN_DIR}) set(Qt3DExtras_libraries pyside2 - ${Qt53DExtras_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DExtras_LIBRARIES}) set(Qt3DExtras_deps Qt3DRender) diff --git a/sources/pyside2/PySide2/Qt3DInput/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DInput/CMakeLists.txt index a910e30df..8c87b4332 100644 --- a/sources/pyside2/PySide2/Qt3DInput/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DInput/CMakeLists.txt @@ -31,14 +31,14 @@ set(Qt3DInput_include_dirs ${Qt3DInput_SOURCE_DIR} ${Qt3DInput_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${Qt3DCore_GEN_DIR}) set(Qt3DInput_libraries pyside2 - ${Qt53DInput_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DInput_LIBRARIES}) set(Qt3DInput_deps Qt3DCore) diff --git a/sources/pyside2/PySide2/Qt3DLogic/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DLogic/CMakeLists.txt index 09306f480..9197c3542 100644 --- a/sources/pyside2/PySide2/Qt3DLogic/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DLogic/CMakeLists.txt @@ -11,15 +11,15 @@ set(Qt3DLogic_include_dirs ${Qt3DLogic_SOURCE_DIR} ${Qt3DLogic_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${Qt3DCore_GEN_DIR}) set(Qt3DLogic_libraries pyside2 - ${Qt53DLogic_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DLogic_LIBRARIES}) set(Qt3DLogic_deps Qt3DCore) diff --git a/sources/pyside2/PySide2/Qt3DRender/CMakeLists.txt b/sources/pyside2/PySide2/Qt3DRender/CMakeLists.txt index edd023840..32f28e032 100644 --- a/sources/pyside2/PySide2/Qt3DRender/CMakeLists.txt +++ b/sources/pyside2/PySide2/Qt3DRender/CMakeLists.txt @@ -106,7 +106,8 @@ ${Qt3DRender_GEN_DIR}/qt3drender_qviewport_wrapper.cpp # module is always needed ${Qt3DRender_GEN_DIR}/qt3drender_module_wrapper.cpp) -if (Qt53DRender_VERSION VERSION_EQUAL 5.10.0 OR Qt53DRender_VERSION VERSION_GREATER 5.10.0) +if (Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_EQUAL 5.10.0 + OR Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_GREATER 5.10.0) list(APPEND Qt3DRender_SRC ${Qt3DRender_GEN_DIR}/qt3drender_qblitframebuffer_wrapper.cpp ${Qt3DRender_GEN_DIR}/qt3drender_qlinewidth_wrapper.cpp @@ -117,7 +118,8 @@ if (Qt53DRender_VERSION VERSION_EQUAL 5.10.0 OR Qt53DRender_VERSION VERSION_GREA ) endif() -if (Qt53DRender_VERSION VERSION_EQUAL 5.11.0 OR Qt53DRender_VERSION VERSION_GREATER 5.11.0) +if (Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_EQUAL 5.11.0 + OR Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_GREATER 5.11.0) list(APPEND Qt3DRender_SRC ${Qt3DRender_GEN_DIR}/qt3drender_qabstractraycaster_wrapper.cpp ${Qt3DRender_GEN_DIR}/qt3drender_qraycaster_wrapper.cpp @@ -125,32 +127,40 @@ if (Qt53DRender_VERSION VERSION_EQUAL 5.11.0 OR Qt53DRender_VERSION VERSION_GREA ${Qt3DRender_GEN_DIR}/qt3drender_qscreenraycaster_wrapper.cpp) endif() -if (Qt53DRender_VERSION VERSION_EQUAL 5.13.0 OR Qt53DRender_VERSION VERSION_GREATER 5.13.0) +if (Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_EQUAL 5.13.0 + OR Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_GREATER 5.13.0) list(APPEND Qt3DRender_SRC ${Qt3DRender_GEN_DIR}/qt3drender_qsetfence_wrapper.cpp ${Qt3DRender_GEN_DIR}/qt3drender_qsharedgltexture_wrapper.cpp ${Qt3DRender_GEN_DIR}/qt3drender_qwaitfence_wrapper.cpp) endif() -if (Qt53DRender_VERSION VERSION_EQUAL 5.14.0 OR Qt53DRender_VERSION VERSION_GREATER 5.14.0) +if (Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_EQUAL 5.14.0 + OR Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_GREATER 5.14.0) list(APPEND Qt3DRender_SRC ${Qt3DRender_GEN_DIR}/qt3drender_qnopicking_wrapper.cpp ${Qt3DRender_GEN_DIR}/qt3drender_qshaderimage_wrapper.cpp) endif() +if (Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_EQUAL 5.15.0 + OR Qt${QT_MAJOR_VERSION}3DRender_VERSION VERSION_GREATER 5.15.0) + list(APPEND Qt3DRender_SRC + ${Qt3DRender_GEN_DIR}/qt3drender_qrendercapabilities_wrapper.cpp) +endif() + set(Qt3DRender_include_dirs ${Qt3DRender_SOURCE_DIR} ${Qt3DRender_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${Qt3DCore_GEN_DIR}) set(Qt3DRender_libraries pyside2 - ${Qt53DRender_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}3DRender_LIBRARIES}) set(Qt3DRender_deps Qt3DCore) diff --git a/sources/pyside2/PySide2/Qt3DRender/typesystem_3drender.xml b/sources/pyside2/PySide2/Qt3DRender/typesystem_3drender.xml index 477dc605d..1ab13d7d7 100644 --- a/sources/pyside2/PySide2/Qt3DRender/typesystem_3drender.xml +++ b/sources/pyside2/PySide2/Qt3DRender/typesystem_3drender.xml @@ -184,6 +184,10 @@ <object-type name="QRenderAspect"> <enum-type name="RenderType"/> </object-type> + <object-type name="QRenderCapabilities" since="5.15"> + <enum-type name="API"/> + <enum-type name="Profile"/> + </object-type> <object-type name="QRenderCapture"/> <object-type name="QRenderCaptureReply"/> <object-type name="QRenderPass"/> diff --git a/sources/pyside2/PySide2/QtAxContainer/CMakeLists.txt b/sources/pyside2/PySide2/QtAxContainer/CMakeLists.txt index d7de684b9..38e764405 100644 --- a/sources/pyside2/PySide2/QtAxContainer/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtAxContainer/CMakeLists.txt @@ -18,17 +18,17 @@ set(QtAxContainer_include_dirs ${QtAxContainer_SOURCE_DIR} ${QtAxContainer_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR}) set(QtAxContainer_libraries pyside2 - ${Qt5AxContainer_LIBRARIES} - ${Qt5AxBase_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}AxContainer_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}AxBase_LIBRARIES}) set(QtAxContainer_deps QtWidgets) diff --git a/sources/pyside2/PySide2/QtCharts/CMakeLists.txt b/sources/pyside2/PySide2/QtCharts/CMakeLists.txt index a327017a7..f73a28b7d 100644 --- a/sources/pyside2/PySide2/QtCharts/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtCharts/CMakeLists.txt @@ -60,20 +60,20 @@ ${QtCharts_GEN_DIR}/qtcharts_module_wrapper.cpp set(QtCharts_include_dirs ${QtCharts_SOURCE_DIR} ${QtCharts_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Charts_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Charts_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR}) set(QtCharts_libraries pyside2 - ${Qt5Charts_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Charts_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES}) set(QtCharts_deps QtCore QtGui QtWidgets) diff --git a/sources/pyside2/PySide2/QtConcurrent/CMakeLists.txt b/sources/pyside2/PySide2/QtConcurrent/CMakeLists.txt index b9c5e4b75..145a8bfc3 100644 --- a/sources/pyside2/PySide2/QtConcurrent/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtConcurrent/CMakeLists.txt @@ -8,14 +8,14 @@ ${QtConcurrent_GEN_DIR}/qtconcurrent_module_wrapper.cpp set(QtConcurrent_include_dirs ${QtConcurrent_SOURCE_DIR} ${QtConcurrent_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Concurrent_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Concurrent_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtConcurrent_libraries pyside2 ${QtConcurrent_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtConcurrent_deps QtCore) diff --git a/sources/pyside2/PySide2/QtCore/CMakeLists.txt b/sources/pyside2/PySide2/QtCore/CMakeLists.txt index c1add5f21..cfba8d3f1 100644 --- a/sources/pyside2/PySide2/QtCore/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtCore/CMakeLists.txt @@ -129,6 +129,7 @@ ${QtCore_GEN_DIR}/qsignalmapper_wrapper.cpp ${QtCore_GEN_DIR}/qsignaltransition_wrapper.cpp ${QtCore_GEN_DIR}/qsize_wrapper.cpp ${QtCore_GEN_DIR}/qsizef_wrapper.cpp +${QtCore_GEN_DIR}/qsocketdescriptor_wrapper.cpp ${QtCore_GEN_DIR}/qsocketnotifier_wrapper.cpp ${QtCore_GEN_DIR}/qsortfilterproxymodel_wrapper.cpp ${QtCore_GEN_DIR}/qstate_wrapper.cpp @@ -181,13 +182,15 @@ ${SPECIFIC_OS_FILES} ${QtCore_GEN_DIR}/qtcore_module_wrapper.cpp ) -if (Qt5Core_VERSION VERSION_EQUAL 5.13.0 OR Qt5Core_VERSION VERSION_GREATER 5.13.0) +if (Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_EQUAL 5.13.0 + OR Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_GREATER 5.13.0) list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qconcatenatetablesproxymodel_wrapper.cpp ${QtCore_GEN_DIR}/qtransposeproxymodel_wrapper.cpp) endif() -if (Qt5Core_VERSION VERSION_EQUAL 5.14.0 OR Qt5Core_VERSION VERSION_GREATER 5.14.0) +if (Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_EQUAL 5.14.0 + OR Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_GREATER 5.14.0) list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qcalendar_wrapper.cpp ${QtCore_GEN_DIR}/qcalendar_yearmonthday_wrapper.cpp @@ -204,11 +207,11 @@ configure_file("${QtCore_SOURCE_DIR}/typesystem_core.xml.in" set(QtCore_include_dirs ${QtCore_SOURCE_DIR} ${QtCore_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ) set(QtCore_libraries pyside2 - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) create_pyside_module(NAME QtCore diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 26193a0aa..e79123398 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -656,6 +656,13 @@ </namespace-type> + <add-function signature="QEnum(PyObject*)" return-type="PyObject*"> + <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qt-qenum"/> + </add-function> + <add-function signature="QFlag(PyObject*)" return-type="PyObject*"> + <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qt-qflag"/> + </add-function> + <add-function signature="qAbs(double)" return-type="double"> <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qt-qabs"/> </add-function> @@ -789,7 +796,7 @@ </modify-function> </object-type> - <value-type name="QBasicTimer"/> + <object-type name="QBasicTimer"/> <value-type name="QByteArrayMatcher"/> <value-type name="QCalendar" since="5.14"> <value-type name="YearMonthDay"/> @@ -1467,6 +1474,7 @@ <modify-function signature="msleep(unsigned long)" allow-thread="yes"/> <modify-function signature="sleep(unsigned long)" allow-thread="yes"/> <modify-function signature="usleep(unsigned long)" allow-thread="yes"/> + <modify-function signature="wait(QDeadlineTimer)" allow-thread="yes"/> <modify-function signature="wait(unsigned long)" allow-thread="yes"/> <modify-function signature="yieldCurrentThread()" allow-thread="yes"/> <modify-function signature="start(QThread::Priority)" allow-thread="yes"> @@ -1541,7 +1549,7 @@ <enum-type name="SelectionFlag" flags="SelectionFlags"/> </object-type> - <value-type name="QItemSelectionRange" hash-function="qHash"> + <value-type name="QItemSelectionRange"> </value-type> <object-type name="QAbstractProxyModel" polymorphic-id-expression="qobject_cast<QAbstractProxyModel*>(%1)"> <extra-includes> @@ -2342,6 +2350,9 @@ </object-type> <object-type name="QSemaphoreReleaser" since="5.10"/> + <value-type name="QSocketDescriptor" since="5.15"> + <inject-code class="native" position="beginning" file="../glue/qtcore.cpp" snippet="qsocketdescriptor"/> + </value-type> <object-type name="QSocketNotifier"> <enum-type name="Type"/> <add-function signature="QSocketNotifier(PyObject*, QSocketNotifier::Type, QObject*)"> @@ -2417,7 +2428,9 @@ </modify-function> </object-type> <object-type name="QWaitCondition"> + <modify-function signature="wait(QMutex*,QDeadlineTimer)" allow-thread="yes"/> <modify-function signature="wait(QMutex*,unsigned long)" allow-thread="yes"/> + <modify-function signature="wait(QReadWriteLock*,QDeadlineTimer)" allow-thread="yes"/> <modify-function signature="wait(QReadWriteLock*,unsigned long)" allow-thread="yes"/> </object-type> <object-type name="QFileSystemWatcher"> diff --git a/sources/pyside2/PySide2/QtDataVisualization/CMakeLists.txt b/sources/pyside2/PySide2/QtDataVisualization/CMakeLists.txt index 40dafdc4e..46868fe35 100644 --- a/sources/pyside2/PySide2/QtDataVisualization/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtDataVisualization/CMakeLists.txt @@ -43,17 +43,17 @@ ${QtDataVisualization_GEN_DIR}/qtdatavisualization_module_wrapper.cpp set(QtDataVisualization_include_dirs ${QtDataVisualization_SOURCE_DIR} ${QtDataVisualization_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5DataVisualization_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}DataVisualization_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR}) set(QtDataVisualization_libraries pyside2 - ${Qt5DataVisualization_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}DataVisualization_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtDataVisualization_deps QtCore QtGui) diff --git a/sources/pyside2/PySide2/QtGui/CMakeLists.txt b/sources/pyside2/PySide2/QtGui/CMakeLists.txt index 9e6bd099f..0001d51d6 100644 --- a/sources/pyside2/PySide2/QtGui/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtGui/CMakeLists.txt @@ -1,10 +1,14 @@ project(QtGui) -qt5_wrap_cpp(QPYTEXTOBJECT_MOC "${pyside2_SOURCE_DIR}/qpytextobject.h") +if (${QT_MAJOR_VERSION} GREATER_EQUAL 6) + qt6_wrap_cpp(QPYTEXTOBJECT_MOC "${pyside2_SOURCE_DIR}/qpytextobject.h") +else() + qt5_wrap_cpp(QPYTEXTOBJECT_MOC "${pyside2_SOURCE_DIR}/qpytextobject.h") +endif() set(QtGui_DROPPED_ENTRIES) -get_property(QtGui_enabled_features TARGET Qt5::Gui PROPERTY INTERFACE_QT_ENABLED_FEATURES) +get_property(QtGui_enabled_features TARGET Qt${QT_MAJOR_VERSION}::Gui PROPERTY INTERFACE_QT_ENABLED_FEATURES) set(QtGui_SRC ${QtGui_GEN_DIR}/qabstractopenglfunctions_wrapper.cpp @@ -134,6 +138,7 @@ ${QtGui_GEN_DIR}/qpytextobject_wrapper.cpp ${QtGui_GEN_DIR}/qquaternion_wrapper.cpp ${QtGui_GEN_DIR}/qradialgradient_wrapper.cpp ${QtGui_GEN_DIR}/qregexpvalidator_wrapper.cpp +${QtGui_GEN_DIR}/qregularexpressionvalidator_wrapper.cpp ${QtGui_GEN_DIR}/qregion_wrapper.cpp ${QtGui_GEN_DIR}/qresizeevent_wrapper.cpp ${QtGui_GEN_DIR}/qsessionmanager_wrapper.cpp @@ -210,7 +215,8 @@ ${QtGui_GEN_DIR}/qwindowstatechangeevent_wrapper.cpp ${QtGui_GEN_DIR}/qtgui_module_wrapper.cpp ) -if (Qt5Gui_VERSION VERSION_EQUAL 5.14.0 OR Qt5Gui_VERSION VERSION_GREATER 5.14.0) +if (Qt${QT_MAJOR_VERSION}Gui_VERSION VERSION_EQUAL 5.14.0 + OR Qt${QT_MAJOR_VERSION}Gui_VERSION VERSION_GREATER 5.14.0) list(APPEND QtGui_SRC ${QtGui_GEN_DIR}/qcolorspace_wrapper.cpp) endif() @@ -219,12 +225,12 @@ list(FIND QtGui_enabled_features "opengles2" _opengles2Index) # ### fixme: For cmake >= 3.3: if(opengles2 IN_LIST QtGui_enabled_features) if(_opengles2Index GREATER -1) list(APPEND QtGui_DROPPED_ENTRIES QOpenGLTimeMonitor QOpenGLTimerQuery) - message(STATUS "Qt5Gui: Dropping Desktop OpenGL classes (GLES2)") + message(STATUS "Qt${QT_MAJOR_VERSION}Gui: Dropping Desktop OpenGL classes (GLES2)") else() list(APPEND QtGui_SRC ${QtGui_GEN_DIR}/qopengltimemonitor_wrapper.cpp ${QtGui_GEN_DIR}/qopengltimerquery_wrapper.cpp) - message(STATUS "Qt5Gui: Adding Desktop OpenGL classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Gui: Adding Desktop OpenGL classes") endif() configure_file("${QtGui_SOURCE_DIR}/typesystem_gui.xml.in" @@ -236,13 +242,13 @@ configure_file("${QtGui_SOURCE_DIR}/QtGui_global.post.h.in" set(QtGui_include_dirs ${QtGui_SOURCE_DIR} ${QtGui_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtGui_libraries pyside2 - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtGui_deps QtCore) create_pyside_module(NAME QtGui diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index 13f8f3cbf..f72259569 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -1273,6 +1273,7 @@ </object-type> <object-type name="QRegExpValidator"/> + <object-type name="QRegularExpressionValidator"/> <object-type name="QStandardItem"> <enum-type name="ItemType"/> diff --git a/sources/pyside2/PySide2/QtHelp/CMakeLists.txt b/sources/pyside2/PySide2/QtHelp/CMakeLists.txt index 4262bcd1a..267703f6e 100644 --- a/sources/pyside2/PySide2/QtHelp/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtHelp/CMakeLists.txt @@ -17,29 +17,38 @@ ${QtHelp_GEN_DIR}/qhelpsearchresultwidget_wrapper.cpp ${QtHelp_GEN_DIR}/qthelp_module_wrapper.cpp ) -if (Qt5Help_VERSION VERSION_EQUAL 5.13.0 OR Qt5Help_VERSION VERSION_GREATER 5.13.0) +if (Qt${QT_MAJOR_VERSION}Help_VERSION VERSION_EQUAL 5.13.0 + OR Qt${QT_MAJOR_VERSION}Help_VERSION VERSION_GREATER 5.13.0) list(APPEND QtHelp_SRC ${QtHelp_GEN_DIR}/qcompressedhelpinfo_wrapper.cpp ${QtHelp_GEN_DIR}/qhelpfilterdata_wrapper.cpp ${QtHelp_GEN_DIR}/qhelpfilterengine_wrapper.cpp) endif() +if (Qt${QT_MAJOR_VERSION}Help_VERSION VERSION_EQUAL 5.15.0 + OR Qt${QT_MAJOR_VERSION}Help_VERSION VERSION_GREATER 5.15.0) + list(APPEND QtHelp_SRC + ${QtHelp_GEN_DIR}/qhelpfiltersettingswidget_wrapper.cpp + ${QtHelp_GEN_DIR}/qhelplink_wrapper.cpp) +endif() + + set(QtHelp_include_dirs ${QtHelp_SOURCE_DIR} ${QtHelp_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Help_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Help_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtWidgets_GEN_DIR} ${QtGui_GEN_DIR} ${QtCore_GEN_DIR} ) set(QtHelp_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Help_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Help_LIBRARIES}) set(QtHelp_deps QtWidgets) diff --git a/sources/pyside2/PySide2/QtHelp/typesystem_help.xml b/sources/pyside2/PySide2/QtHelp/typesystem_help.xml index cd62f8afd..76013d1ac 100644 --- a/sources/pyside2/PySide2/QtHelp/typesystem_help.xml +++ b/sources/pyside2/PySide2/QtHelp/typesystem_help.xml @@ -57,8 +57,10 @@ <object-type name="QHelpEngineCore"/> <value-type name="QHelpFilterData" since="5.13"/> <object-type name="QHelpFilterEngine" since="5.13"/> + <object-type name="QHelpFilterSettingsWidget" since="5.15"/> <object-type name="QHelpIndexModel"/> <object-type name="QHelpIndexWidget"/> + <value-type name="QHelpLink" since="5.15"/> <object-type name="QHelpSearchEngine"/> <value-type name="QHelpSearchQuery"> <enum-type name="FieldName"/> diff --git a/sources/pyside2/PySide2/QtLocation/CMakeLists.txt b/sources/pyside2/PySide2/QtLocation/CMakeLists.txt index 37cc7e6e5..fa21310b7 100644 --- a/sources/pyside2/PySide2/QtLocation/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtLocation/CMakeLists.txt @@ -47,21 +47,22 @@ ${QtLocation_GEN_DIR}/qplacesupplier_wrapper.cpp ${QtLocation_GEN_DIR}/qtlocation_module_wrapper.cpp ) -if (Qt5Location_VERSION VERSION_EQUAL 5.11.0 OR Qt5Location_VERSION VERSION_GREATER 5.11.0) +if (Qt${QT_MAJOR_VERSION}Location_VERSION VERSION_EQUAL 5.11.0 + OR Qt${QT_MAJOR_VERSION}Location_VERSION VERSION_GREATER 5.11.0) list(APPEND QtLocation_SRC ${QtLocation_GEN_DIR}/qgeoserviceproviderfactoryv2_wrapper.cpp) endif() set(QtLocation_include_dirs ${QtLocation_SOURCE_DIR} ${QtLocation_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Location_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Location_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtPositioning_GEN_DIR}) set(QtLocation_libraries pyside2 - ${Qt5Location_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Location_LIBRARIES}) set(QtLocation_deps QtCore QtPositioning) diff --git a/sources/pyside2/PySide2/QtMacExtras/CMakeLists.txt b/sources/pyside2/PySide2/QtMacExtras/CMakeLists.txt index efa7944b1..6e3d0f25c 100644 --- a/sources/pyside2/PySide2/QtMacExtras/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtMacExtras/CMakeLists.txt @@ -11,17 +11,17 @@ ${QtMacExtras_GEN_DIR}/qtmacextras_module_wrapper.cpp set(QtMacExtras_include_dirs ${QtMacExtras_SOURCE_DIR} ${QtMacExtras_BINARY_DIR} - ${Qt5MacExtras_INCLUDE_DIRS} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}MacExtras_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${libpyside_SOURCE_DIR}) set(QtMacExtras_libraries pyside2 - ${Qt5MacExtras_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}MacExtras_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtMacExtras_deps QtCore QtGui) diff --git a/sources/pyside2/PySide2/QtMultimedia/CMakeLists.txt b/sources/pyside2/PySide2/QtMultimedia/CMakeLists.txt index cbdd9a1c2..64e6a3a4e 100644 --- a/sources/pyside2/PySide2/QtMultimedia/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtMultimedia/CMakeLists.txt @@ -97,27 +97,28 @@ ${QtMultimedia_GEN_DIR}/qvideowindowcontrol_wrapper.cpp ${QtMultimedia_GEN_DIR}/qtmultimedia_module_wrapper.cpp ) -if (Qt5Multimedia_VERSION VERSION_EQUAL 5.11.0 OR Qt5Multimedia_VERSION VERSION_GREATER 5.11.0) +if (Qt${QT_MAJOR_VERSION}Multimedia_VERSION VERSION_EQUAL 5.11.0 + OR Qt${QT_MAJOR_VERSION}Multimedia_VERSION VERSION_GREATER 5.11.0) list(APPEND QtMultimedia_SRC ${QtMultimedia_GEN_DIR}/qcustomaudiorolecontrol_wrapper.cpp) endif() set(QtMultimedia_include_dirs ${QtMultimedia_SOURCE_DIR} ${QtMultimedia_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Multimedia_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Multimedia_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtNetwork_GEN_DIR}) set(QtMultimedia_libraries pyside2 - ${Qt5Multimedia_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Multimedia_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} ) set(QtMultimedia_deps QtCore QtGui QtNetwork) diff --git a/sources/pyside2/PySide2/QtMultimediaWidgets/CMakeLists.txt b/sources/pyside2/PySide2/QtMultimediaWidgets/CMakeLists.txt index 7448f5f38..052db6c42 100644 --- a/sources/pyside2/PySide2/QtMultimediaWidgets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtMultimediaWidgets/CMakeLists.txt @@ -11,12 +11,12 @@ ${QtMultimediaWidgets_GEN_DIR}/qtmultimediawidgets_module_wrapper.cpp set(QtMultimediaWidgets_include_dirs ${QtMultimediaWidgets_SOURCE_DIR} ${QtMultimediaWidgets_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Multimedia_INCLUDE_DIRS} - ${Qt5MultimediaWidgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Multimedia_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}MultimediaWidgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -25,12 +25,12 @@ set(QtMultimediaWidgets_include_dirs ${QtMultimediaWidgets_SOURCE_DIR} ${QtMultimedia_GEN_DIR}) set(QtMultimediaWidgets_libraries pyside2 - ${Qt5Multimedia_LIBRARIES} - ${Qt5MultimediaWidgets_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Widgets_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Multimedia_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}MultimediaWidgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES}) set(QtMultimediaWidgets_deps QtCore QtGui QtNetwork QtWidgets QtMultimedia) diff --git a/sources/pyside2/PySide2/QtNetwork/CMakeLists.txt b/sources/pyside2/PySide2/QtNetwork/CMakeLists.txt index 7ca3fbb53..7a9dcc23f 100644 --- a/sources/pyside2/PySide2/QtNetwork/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtNetwork/CMakeLists.txt @@ -47,8 +47,10 @@ ${QtNetwork_GEN_DIR}/qudpsocket_wrapper.cpp ${QtNetwork_GEN_DIR}/qtnetwork_module_wrapper.cpp ) -get_property(QtNetwork_enabled_features TARGET Qt5::Network PROPERTY INTERFACE_QT_ENABLED_FEATURES) -get_property(QtNetwork_disabled_features TARGET Qt5::Network PROPERTY INTERFACE_QT_DISABLED_FEATURES) +get_property(QtNetwork_enabled_features TARGET Qt${QT_MAJOR_VERSION}::Network + PROPERTY INTERFACE_QT_ENABLED_FEATURES) +get_property(QtNetwork_disabled_features TARGET Qt${QT_MAJOR_VERSION}::Network + PROPERTY INTERFACE_QT_DISABLED_FEATURES) # ### fixme: For cmake >= 3.3, use if( needle IN_LIST list) list(FIND QtNetwork_enabled_features "ssl" _sslEnabledIndex) @@ -59,7 +61,7 @@ if(_sslEnabledIndex EQUAL -1) list(APPEND QtNetwork_DROPPED_ENTRIES QOcspResponse QSslCipher QSslConfiguration QSslDiffieHellmanParameters QSslError QSslKey QSslPreSharedKeyAuthenticator QSslSocket) - message(STATUS "Qt5Network: Dropping SSL classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Dropping SSL classes") else() # Problems with operator==(QSslEllipticCurve,QSslEllipticCurve) # check_qt_class(QtNetwork QSslEllipticCurve QtNetwork_OPTIONAL_SRC QtNetwork_DROPPED_ENTRIES) @@ -71,41 +73,42 @@ else() ${QtNetwork_GEN_DIR}/qsslkey_wrapper.cpp ${QtNetwork_GEN_DIR}/qsslpresharedkeyauthenticator_wrapper.cpp ${QtNetwork_GEN_DIR}/qsslsocket_wrapper.cpp) - if (Qt5Network_VERSION VERSION_EQUAL 5.13.0 OR Qt5Network_VERSION VERSION_GREATER 5.13.0) + if (Qt${QT_MAJOR_VERSION}Network_VERSION VERSION_EQUAL 5.13.0 + OR Qt${QT_MAJOR_VERSION}Network_VERSION VERSION_GREATER 5.13.0) list(APPEND QtNetwork_SRC ${QtNetwork_GEN_DIR}/qocspresponse_wrapper.cpp) endif() - message(STATUS "Qt5Network: Adding SSL classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Adding SSL classes") endif() if(_dtlsDisabledIndex GREATER -1) list(APPEND QtNetwork_DROPPED_ENTRIES QDtls) - message(STATUS "Qt5Network: Dropping DTLS classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Dropping DTLS classes") else() list(APPEND QtNetwork_SRC ${QtNetwork_GEN_DIR}/qdtls_wrapper.cpp) - message(STATUS "Qt5Network: Adding DTLS classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Adding DTLS classes") endif() if(_sctpDisabledIndex GREATER -1) list(APPEND QtNetwork_DROPPED_ENTRIES QSctpServer QSctpSocket) - message(STATUS "Qt5Network: Dropping SCTP classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Dropping SCTP classes") else() list(APPEND QtNetwork_SRC ${QtNetwork_GEN_DIR}/qsctpserver_wrapper.cpp ${QtNetwork_GEN_DIR}/qsctpsocket_wrapper.cpp) - message(STATUS "Qt5Network: Adding SCTP classes") + message(STATUS "Qt${QT_MAJOR_VERSION}Network: Adding SCTP classes") endif() set(QtNetwork_include_dirs ${QtNetwork_SOURCE_DIR} ${QtNetwork_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR}) set(QtNetwork_libraries pyside2 - ${Qt5Network_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES}) set(QtNetwork_deps QtCore) diff --git a/sources/pyside2/PySide2/QtNetwork/typesystem_network.xml b/sources/pyside2/PySide2/QtNetwork/typesystem_network.xml index e128d431e..1e473b3a6 100644 --- a/sources/pyside2/PySide2/QtNetwork/typesystem_network.xml +++ b/sources/pyside2/PySide2/QtNetwork/typesystem_network.xml @@ -258,6 +258,7 @@ <enum-type name="CacheLoadControl"/> <enum-type name="KnownHeaders"/> <enum-type name="RedirectPolicy" since="5.9"/> + <enum-type name="TransferTimeoutConstant" since="5.15"/> </value-type> <value-type name="QNetworkConfiguration" since="4.7"> @@ -284,6 +285,7 @@ <!-- The following entries may be present in the system or not. Keep this section organized. --> <value-type name="QSslCertificate"> + <enum-type name="PatternSyntax" since="5.15"/> <enum-type name="SubjectInfo"/> </value-type> diff --git a/sources/pyside2/PySide2/QtOpenGL/CMakeLists.txt b/sources/pyside2/PySide2/QtOpenGL/CMakeLists.txt index 1ca245fea..1d2c406fc 100644 --- a/sources/pyside2/PySide2/QtOpenGL/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtOpenGL/CMakeLists.txt @@ -17,10 +17,10 @@ ${QtOpenGL_GEN_DIR}/qtopengl_module_wrapper.cpp ) set(QtOpenGL_include_dirs ${QtOpenGL_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5OpenGL_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}OpenGL_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtWidgets_GEN_DIR} ${QtGui_GEN_DIR} @@ -28,10 +28,10 @@ set(QtOpenGL_include_dirs ${QtOpenGL_SOURCE_DIR} ${QtOpenGL_GEN_DIR} ) set(QtOpenGL_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5OpenGL_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}OpenGL_LIBRARIES}) set(QtOpenGL_deps QtWidgets) create_pyside_module(NAME QtOpenGL diff --git a/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt b/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt index 72b3a16ca..eab543b6a 100644 --- a/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt @@ -2,7 +2,8 @@ project(QtOpenGLFunctions) set(QtOpenGLFunctions_DROPPED_ENTRIES) -get_property(QtOpenGLFunctions_enabled_features TARGET Qt5::Gui PROPERTY INTERFACE_QT_ENABLED_FEATURES) +get_property(QtOpenGLFunctions_enabled_features TARGET Qt${QT_MAJOR_VERSION}::Gui + PROPERTY INTERFACE_QT_ENABLED_FEATURES) set(QtOpenGLFunctions_SRC ${QtOpenGLFunctions_GEN_DIR}/qtopenglfunctions_module_wrapper.cpp) @@ -13,7 +14,7 @@ if(_opengles2Index GREATER -1) list(APPEND QtOpenGLFunctions_DROPPED_ENTRIES QOpenGLTimeMonitor QOpenGLTimerQuery) list(APPEND QtOpenGLFunctions_SRC ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_es2_wrapper.cpp) - message(STATUS "Qt5OpenGLFunctions: Dropping Desktop OpenGL classes (GLES2)") + message(STATUS "Qt${QT_MAJOR_VERSION}OpenGLFunctions: Dropping Desktop OpenGL classes (GLES2)") else() list(APPEND QtOpenGLFunctions_SRC ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_1_0_wrapper.cpp @@ -42,7 +43,7 @@ else() ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_4_core_wrapper.cpp ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_5_compatibility_wrapper.cpp ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_5_core_wrapper.cpp) - message(STATUS "Qt5OpenGLFunctions: Adding Desktop OpenGL classes") + message(STATUS "Qt${QT_MAJOR_VERSION}OpenGLFunctions: Adding Desktop OpenGL classes") endif() configure_file("${QtOpenGLFunctions_SOURCE_DIR}/QtOpenGLFunctions_global.post.h.in" @@ -51,14 +52,14 @@ configure_file("${QtOpenGLFunctions_SOURCE_DIR}/QtOpenGLFunctions_global.post.h. set(QtOpenGLFunctions_include_dirs ${QtGOpenGLFunctions_SOURCE_DIR} ${QtOpenGLFunctions_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ) set(QtOpenGLFunctions_libraries pyside2 - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtOpenGLFunctions_deps QtGui) diff --git a/sources/pyside2/PySide2/QtPositioning/CMakeLists.txt b/sources/pyside2/PySide2/QtPositioning/CMakeLists.txt index 4745cb492..321478c3e 100644 --- a/sources/pyside2/PySide2/QtPositioning/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtPositioning/CMakeLists.txt @@ -23,20 +23,21 @@ ${QtPositioning_GEN_DIR}/qnmeapositioninfosource_wrapper.cpp ${QtPositioning_GEN_DIR}/qtpositioning_module_wrapper.cpp ) -if (Qt5Positioning_VERSION VERSION_EQUAL 5.10.0 OR Qt5Positioning_VERSION VERSION_GREATER 5.10.0) +if (Qt${QT_MAJOR_VERSION}Positioning_VERSION VERSION_EQUAL 5.10.0 + OR Qt${QT_MAJOR_VERSION}Positioning_VERSION VERSION_GREATER 5.10.0) list(APPEND QtPositioning_SRC ${QtPositioning_GEN_DIR}/qgeopolygon_wrapper.cpp) endif() set(QtPositioning_include_dirs ${QtPositioning_SOURCE_DIR} ${QtPositioning_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Positioning_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Positioning_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR}) set(QtPositioning_libraries pyside2 - ${Qt5Positioning_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Positioning_LIBRARIES}) set(QtPositioning_deps QtCore) diff --git a/sources/pyside2/PySide2/QtPrintSupport/CMakeLists.txt b/sources/pyside2/PySide2/QtPrintSupport/CMakeLists.txt index 74d3dfb88..fd39797da 100644 --- a/sources/pyside2/PySide2/QtPrintSupport/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtPrintSupport/CMakeLists.txt @@ -18,20 +18,20 @@ configure_file("${QtPrintSupport_SOURCE_DIR}/typesystem_printsupport.xml.in" set(QtPrintSupport_include_dirs ${QtPrintSupport_SOURCE_DIR} ${QtPrintSupport_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5PrintSupport_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}PrintSupport_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR} ) set(QtPrintSupport_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5PrintSupport_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}PrintSupport_LIBRARIES} ) set(QtPrintSupport_deps QtWidgets) create_pyside_module(NAME QtPrintSupport diff --git a/sources/pyside2/PySide2/QtQml/CMakeLists.txt b/sources/pyside2/PySide2/QtQml/CMakeLists.txt index 9912016ef..3c5dd43fc 100644 --- a/sources/pyside2/PySide2/QtQml/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtQml/CMakeLists.txt @@ -36,10 +36,10 @@ ${QtQml_GEN_DIR}/qtqml_module_wrapper.cpp ) set(QtQml_include_dirs ${QtQml_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Qml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtGui_GEN_DIR} ${QtCore_GEN_DIR} @@ -47,10 +47,10 @@ set(QtQml_include_dirs ${QtQml_SOURCE_DIR} ${QtQml_GEN_DIR}) set(QtQml_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Qml_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES}) set(QtQml_deps QtGui QtNetwork) diff --git a/sources/pyside2/PySide2/QtQuick/CMakeLists.txt b/sources/pyside2/PySide2/QtQuick/CMakeLists.txt index 6707c210a..0f453c90e 100644 --- a/sources/pyside2/PySide2/QtQuick/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtQuick/CMakeLists.txt @@ -51,7 +51,7 @@ ${QtQuick_GEN_DIR}/qsgtransformnode_wrapper.cpp ${QtQuick_GEN_DIR}/qtquick_module_wrapper.cpp ) -if (Qt5Quick_VERSION VERSION_GREATER 5.5.1) +if (Qt${QT_MAJOR_VERSION}Quick_VERSION VERSION_GREATER 5.5.1) set(QtQuick_SRC ${QtQuick_SRC} ${QtQuick_GEN_DIR}/qquickasyncimageprovider_wrapper.cpp ${QtQuick_GEN_DIR}/qquickimageresponse_wrapper.cpp @@ -60,11 +60,11 @@ endif() set(QtQuick_include_dirs ${QtQuick_SOURCE_DIR} ${QtQml_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Qml_INCLUDE_DIRS} - ${Qt5Quick_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Quick_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtGui_GEN_DIR} ${QtCore_GEN_DIR} @@ -73,11 +73,11 @@ set(QtQuick_include_dirs ${QtQuick_SOURCE_DIR} ${QtQuick_GEN_DIR}) set(QtQuick_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Qml_LIBRARIES} - ${Qt5Quick_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Quick_LIBRARIES}) set(QtQuick_deps QtGui QtNetwork QtQml) diff --git a/sources/pyside2/PySide2/QtQuickControls2/CMakeLists.txt b/sources/pyside2/PySide2/QtQuickControls2/CMakeLists.txt new file mode 100644 index 000000000..8321d8a3e --- /dev/null +++ b/sources/pyside2/PySide2/QtQuickControls2/CMakeLists.txt @@ -0,0 +1,41 @@ +project(QtQuickControls2) + +set(QtQuickControls2_SRC +${QtQuickControls2_GEN_DIR}/qquickstyle_wrapper.cpp +# module is always needed +${QtQuickControls2_GEN_DIR}/qtquickcontrols2_module_wrapper.cpp +) + + +set(QtQuickControls2_include_dirs ${QtQuickControls2_SOURCE_DIR} + ${QtQml_SOURCE_DIR} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Quick_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}QuickControls2_INCLUDE_DIRS} + ${libpyside_SOURCE_DIR} + ${QtGui_GEN_DIR} + ${QtCore_GEN_DIR} + ${QtNetwork_GEN_DIR} + ${QtQml_GEN_DIR} + ${QtQuick_GEN_DIR} + ${QtQuickControls2_GEN_DIR}) + +set(QtQuickControls2_libraries pyside2 + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Quick_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}QuickControls2_LIBRARIES}) + +set(QtQuickControls2_deps QtGui QtNetwork QtQml QtQuick) + +create_pyside_module(NAME QtQuickControls2 + INCLUDE_DIRS QtQuickControls2_include_dirs + LIBRARIES QtQuickControls2_libraries + DEPS QtQuickControls2_deps + TYPESYSTEM_PATH QtQuickControls2_SOURCE_DIR + SOURCES QtQuickControls2_SRC) diff --git a/sources/pyside2/libpyside/destroylistener.cpp b/sources/pyside2/PySide2/QtQuickControls2/typesystem_quickcontrols2.xml index 319a126cf..51d42b46b 100644 --- a/sources/pyside2/libpyside/destroylistener.cpp +++ b/sources/pyside2/PySide2/QtQuickControls2/typesystem_quickcontrols2.xml @@ -1,6 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -36,68 +38,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +--> +<typesystem package="PySide2.QtQuickControls2"> + <load-typesystem name="QtQuick/typesystem_quick.xml" generate="no"/> -#include <sbkpython.h> -#include "destroylistener.h" - -#include <shiboken.h> - -PySide::DestroyListener *PySide::DestroyListener::m_instance = nullptr; - -namespace PySide -{ - -struct DestroyListenerPrivate -{ - static bool m_destroyed; -}; - - -DestroyListener *DestroyListener::instance() -{ - if (!m_instance) - m_instance = new DestroyListener(0); - return m_instance; -} - -void DestroyListener::destroy() -{ - if (m_instance) { - m_instance->disconnect(); - delete m_instance; - m_instance = 0; - } -} - -void DestroyListener::listen(QObject *obj) -{ - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj); - if (!wrapper) // avoid problem with multiple inheritance - return; - - if (Py_IsInitialized() == 0) - onObjectDestroyed(obj); - else - QObject::connect(obj, SIGNAL(destroyed(QObject *)), this, SLOT(onObjectDestroyed(QObject *)), Qt::DirectConnection); -} - -void DestroyListener::onObjectDestroyed(QObject *obj) -{ - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj); - if (wrapper) //make sure the object exists before destroy - Shiboken::Object::destroy(wrapper, obj); -} - -DestroyListener::DestroyListener(QObject *parent) - : QObject(parent) -{ - m_d = new DestroyListenerPrivate(); -} - -DestroyListener::~DestroyListener() -{ - delete m_d; -} - -}//namespace + <object-type name="QQuickStyle" since="5.7"/> +</typesystem> diff --git a/sources/pyside2/PySide2/QtQuickWidgets/CMakeLists.txt b/sources/pyside2/PySide2/QtQuickWidgets/CMakeLists.txt index 1f5ae7980..4da9bf838 100644 --- a/sources/pyside2/PySide2/QtQuickWidgets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtQuickWidgets/CMakeLists.txt @@ -8,13 +8,13 @@ ${QtQuickWidgets_GEN_DIR}/qtquickwidgets_module_wrapper.cpp set(QtQuickWidgets_include_dirs ${QtQuickWidgets_SOURCE_DIR} ${QtQml_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Quick_INCLUDE_DIRS} - ${Qt5Qml_INCLUDE_DIRS} - ${Qt5QuickWidgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Quick_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}QuickWidgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtGui_GEN_DIR} ${QtCore_GEN_DIR} @@ -25,13 +25,13 @@ set(QtQuickWidgets_include_dirs ${QtQuickWidgets_SOURCE_DIR} ${QtQuickWidgets_GEN_DIR}) set(QtQuickWidgets_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Quick_LIBRARIES} - ${Qt5Qml_LIBRARIES} - ${Qt5QuickWidgets_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Quick_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}QuickWidgets_LIBRARIES}) set(QtQuickWidgets_deps QtGui QtQml QtQuick QtWidgets QtNetwork) diff --git a/sources/pyside2/PySide2/QtRemoteObjects/CMakeLists.txt b/sources/pyside2/PySide2/QtRemoteObjects/CMakeLists.txt index 29b49d895..d8fd6674f 100644 --- a/sources/pyside2/PySide2/QtRemoteObjects/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtRemoteObjects/CMakeLists.txt @@ -21,7 +21,7 @@ ${QtRemoteObjects_GEN_DIR}/qtremoteobjects_module_wrapper.cpp set(QtRemoteObjects_include_dirs ${QtRemoteObjects_SOURCE_DIR} ${QtRemoteObjects_BINARY_DIR} - ${Qt5RemoteObjects_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}RemoteObjects_INCLUDE_DIRS} ${SHIBOKEN_INCLUDE_DIR} ${libpyside_SOURCE_DIR} ${SHIBOKEN_PYTHON_INCLUDE_DIR} @@ -30,7 +30,7 @@ set(QtRemoteObjects_include_dirs ${QtRemoteObjects_SOURCE_DIR} set(QtRemoteObjects_libraries pyside2 ${SHIBOKEN_PYTHON_LIBRARIES} ${SHIBOKEN_LIBRARY} - ${Qt5RemoteObjects_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}RemoteObjects_LIBRARIES}) set(QtRemoteObjects_deps QtCore QtNetwork) diff --git a/sources/pyside2/PySide2/QtScript/CMakeLists.txt b/sources/pyside2/PySide2/QtScript/CMakeLists.txt index 12453729b..81d6c03d3 100644 --- a/sources/pyside2/PySide2/QtScript/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtScript/CMakeLists.txt @@ -24,14 +24,14 @@ set(QtScript_glue_sources set(QtScript_include_dirs ${QtScript_SOURCE_DIR} ${QtScript_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Script_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Script_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtScript_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Script_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Script_LIBRARIES}) set(QtScript_deps QtCore) create_pyside_module(NAME QtScript INCLUDE_DIRS QtScript_include_dirs diff --git a/sources/pyside2/PySide2/QtScriptTools/CMakeLists.txt b/sources/pyside2/PySide2/QtScriptTools/CMakeLists.txt index ddb4bec8f..7c19856cb 100644 --- a/sources/pyside2/PySide2/QtScriptTools/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtScriptTools/CMakeLists.txt @@ -8,11 +8,11 @@ ${QtScriptTools_GEN_DIR}/qtscripttools_module_wrapper.cpp set(QtScriptTools_include_dirs ${QtScriptTools_SOURCE_DIR} ${QtScriptTools_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Script_INCLUDE_DIRS} - ${Qt5ScriptTools_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Script_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}ScriptTools_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -21,11 +21,11 @@ set(QtScriptTools_include_dirs ${QtScriptTools_SOURCE_DIR} ) set(QtScriptTools_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Script_LIBRARIES} - ${Qt5ScriptTools_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Script_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}ScriptTools_LIBRARIES}) set(QtScriptTools_deps QtCore QtScript QtGui QtWidgets) diff --git a/sources/pyside2/PySide2/QtScxml/CMakeLists.txt b/sources/pyside2/PySide2/QtScxml/CMakeLists.txt index 9cf2f0b22..732253bba 100644 --- a/sources/pyside2/PySide2/QtScxml/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtScxml/CMakeLists.txt @@ -24,7 +24,8 @@ ${QtScxml_GEN_DIR}/qscxmlexecutablecontent_parameterinfo_wrapper.cpp ${QtScxml_GEN_DIR}/qtscxml_module_wrapper.cpp ) -if (Qt5Scxml_VERSION VERSION_EQUAL 5.12.0 OR Qt5Scxml_VERSION VERSION_GREATER 5.12.0) +if (Qt${QT_MAJOR_VERSION}Scxml_VERSION VERSION_EQUAL 5.12.0 + OR Qt${QT_MAJOR_VERSION}Scxml_VERSION VERSION_GREATER 5.12.0) list(APPEND QtScxml_SRC ${QtScxml_GEN_DIR}/qscxmldatamodel_wrapper.cpp ${QtScxml_GEN_DIR}/qscxmldatamodel_foreachloopbody_wrapper.cpp @@ -35,13 +36,13 @@ endif() set(QtScxml_include_dirs ${QtScxml_SOURCE_DIR} ${QtScxml_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Scxml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Scxml_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR}) set(QtScxml_libraries pyside2 - ${Qt5Scxml_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Scxml_LIBRARIES}) set(QtScxml_deps QtCore) diff --git a/sources/pyside2/PySide2/QtSensors/CMakeLists.txt b/sources/pyside2/PySide2/QtSensors/CMakeLists.txt index 2cdd3fe87..0bd6260b7 100644 --- a/sources/pyside2/PySide2/QtSensors/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtSensors/CMakeLists.txt @@ -81,13 +81,13 @@ set(QtSensors_SRC set(QtSensors_include_dirs ${QtSensors_SOURCE_DIR} ${QtSensors_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Sensors_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Sensors_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR}) set(QtSensors_libraries pyside2 - ${Qt5Sensors_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Sensors_LIBRARIES}) set(QtSensors_deps QtCore) diff --git a/sources/pyside2/PySide2/QtSerialPort/CMakeLists.txt b/sources/pyside2/PySide2/QtSerialPort/CMakeLists.txt new file mode 100644 index 000000000..5242cad4a --- /dev/null +++ b/sources/pyside2/PySide2/QtSerialPort/CMakeLists.txt @@ -0,0 +1,31 @@ +project(QtSerialPort) + +set(QtSerialPort_OPTIONAL_SRC ) +set(QtSerialPort_DROPPED_ENTRIES ) + +set(QtSerialPort_SRC + ${QtSerialPort_GEN_DIR}/qserialport_wrapper.cpp + ${QtSerialPort_GEN_DIR}/qserialportinfo_wrapper.cpp +# module is always needed + ${QtSerialPort_GEN_DIR}/qtserialport_module_wrapper.cpp +) + +set(QtSerialPort_include_dirs ${QtSerialPort_SOURCE_DIR} + ${QtSerialPort_BINARY_DIR} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}SerialPort_INCLUDE_DIRS} + ${libpyside_SOURCE_DIR} + ${QtCore_GEN_DIR}) + +set(QtSerialPort_libraries pyside2 + ${Qt${QT_MAJOR_VERSION}SerialPort_LIBRARIES}) + +set(QtSerialPort_deps QtCore) + +create_pyside_module(NAME QtSerialPort + INCLUDE_DIRS QtSerialPort_include_dirs + LIBRARIES QtSerialPort_libraries + DEPS QtSerialPort_deps + TYPESYSTEM_PATH QtSerialPort_SOURCE_DIR + SOURCES QtSerialPort_SRC + DROPPED_ENTRIES QtSerialPort_DROPPED_ENTRIES) diff --git a/sources/pyside2/PySide2/QtSerialPort/typesystem_serialport.xml b/sources/pyside2/PySide2/QtSerialPort/typesystem_serialport.xml new file mode 100644 index 000000000..8548c543e --- /dev/null +++ b/sources/pyside2/PySide2/QtSerialPort/typesystem_serialport.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<typesystem package="PySide2.QtSerialPort"> + <load-typesystem name="QtCore/typesystem_core.xml" generate="no"/> + <object-type name="QSerialPort"> + <enum-type name="BaudRate"/> + <enum-type name="DataBits"/> + <enum-type name="DataErrorPolicy"/> + <enum-type name="Direction" flags="Directions"/> + <enum-type name="FlowControl"/> + <enum-type name="Parity"/> + <enum-type name="PinoutSignal" flags="PinoutSignals"/> + <enum-type name="SerialPortError"/> + <enum-type name="StopBits"/> + </object-type> + <value-type name="QSerialPortInfo"/> +</typesystem> diff --git a/sources/pyside2/PySide2/QtSql/CMakeLists.txt b/sources/pyside2/PySide2/QtSql/CMakeLists.txt index 4abd46694..40a253393 100644 --- a/sources/pyside2/PySide2/QtSql/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtSql/CMakeLists.txt @@ -25,20 +25,20 @@ configure_file("${QtSql_SOURCE_DIR}/QtSql_global.pre.h.in" set(QtSql_include_dirs ${QtSql_SOURCE_DIR} ${QtSql_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Sql_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Sql_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR} ) set(QtSql_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Sql_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Sql_LIBRARIES}) set(QtSql_deps QtWidgets) create_pyside_module(NAME QtSql diff --git a/sources/pyside2/PySide2/QtSvg/CMakeLists.txt b/sources/pyside2/PySide2/QtSvg/CMakeLists.txt index 75b6f2bf5..19768274d 100644 --- a/sources/pyside2/PySide2/QtSvg/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtSvg/CMakeLists.txt @@ -11,20 +11,20 @@ ${QtSvg_GEN_DIR}/qtsvg_module_wrapper.cpp set(QtSvg_include_dirs ${QtSvg_SOURCE_DIR} ${QtSvg_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Svg_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Svg_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR} ) set(QtSvg_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Svg_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Svg_LIBRARIES} ) set(QtSvg_deps QtWidgets) diff --git a/sources/pyside2/PySide2/QtTest/CMakeLists.txt b/sources/pyside2/PySide2/QtTest/CMakeLists.txt index 6614bbca1..04bb28cc9 100644 --- a/sources/pyside2/PySide2/QtTest/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtTest/CMakeLists.txt @@ -15,20 +15,20 @@ configure_file("${QtTest_SOURCE_DIR}/QtTest_global.post.h.in" set(QtTest_include_dirs ${QtTest_SOURCE_DIR} ${QtTest_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Test_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Test_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${QtWidgets_GEN_DIR} ) set(QtTest_libraries pyside2 - ${Qt5Test_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Test_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtTest_deps QtWidgets) diff --git a/sources/pyside2/PySide2/QtTextToSpeech/CMakeLists.txt b/sources/pyside2/PySide2/QtTextToSpeech/CMakeLists.txt index c3080c034..ebd95cfbe 100644 --- a/sources/pyside2/PySide2/QtTextToSpeech/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtTextToSpeech/CMakeLists.txt @@ -10,15 +10,15 @@ ${QtTextToSpeech_GEN_DIR}/qttexttospeech_module_wrapper.cpp set(QtTextToSpeech_include_dirs ${QtTextToSpeech_SOURCE_DIR} ${QtTextToSpeech_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5TextToSpeech_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}TextToSpeech_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR}) set(QtTextToSpeech_libraries pyside2 - ${Qt5Multimedia_LIBRARIES} - ${Qt5TextToSpeech_LIBRARIES} - ${Qt5Core_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Multimedia_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}TextToSpeech_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES}) set(QtTextToSpeech_deps QtCore QtMultimedia) diff --git a/sources/pyside2/PySide2/QtUiTools/CMakeLists.txt b/sources/pyside2/PySide2/QtUiTools/CMakeLists.txt index 1ae44d4fd..f9ca16e5a 100644 --- a/sources/pyside2/PySide2/QtUiTools/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtUiTools/CMakeLists.txt @@ -12,12 +12,12 @@ set(QtUiTools_glue_sources set(QtUiTools_include_dirs ${QtUiTools_SOURCE_DIR} ${QtUiTools_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Xml_INCLUDE_DIRS} - ${Qt5Designer_INCLUDE_DIRS} - ${Qt5UiTools_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Xml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Designer_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}UiTools_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${plugins_SOURCE_DIR} ${QtCore_GEN_DIR} @@ -27,10 +27,10 @@ set(QtUiTools_include_dirs ${QtUiTools_SOURCE_DIR} ) set(QtUiTools_libraries pyside2 uiplugin - ${Qt5UiTools_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}UiTools_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} ) set(QtUiTools_deps QtWidgets QtXml) create_pyside_module(NAME QtUiTools diff --git a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml index 2ca12e788..85092a5c2 100644 --- a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml +++ b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml @@ -146,31 +146,6 @@ Riverbank's PyQt. --> <add-function signature="loadUiType(const QString& @uifile@)" return-type="PyObject*"> - <inject-documentation format="target" mode="append"> - This function will allow users to generate and load a `.ui` file at runtime, and it returns - a `tuple` containing the reference to the Python class, and the base class. - - We don't recommend this approach since the workflow should be to generate a Python file - from the `.ui` file, and then import and load it to use it, but we do understand that - there are some corner cases when such functionality is required. - - The internal process relies on `uic` being in the PATH, which is the same requirement for - the new `pyside2-uic` to work (which is just a wrapper around `uic -g python`) - - A Simple use can be: - - .. code-block:: python - - from PySide2.QtUiTools import loadUiType - - generated_class, base_class = loadUiType("themewidget.ui") - # the values will be: - # (<class '__main__.Ui_ThemeWidgetForm'>, <class 'PySide2.QtWidgets.QWidget'>) - - - In that case, `generated_class` will be a reference to the Python class, - and `base_class` will be a reference to the base class. - </inject-documentation> <inject-code file="../glue/qtuitools.cpp" snippet="loaduitype"/> </add-function> diff --git a/sources/pyside2/PySide2/QtWebChannel/CMakeLists.txt b/sources/pyside2/PySide2/QtWebChannel/CMakeLists.txt index 58957b21e..df9531809 100644 --- a/sources/pyside2/PySide2/QtWebChannel/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebChannel/CMakeLists.txt @@ -9,14 +9,14 @@ ${QtWebChannel_GEN_DIR}/qtwebchannel_module_wrapper.cpp set(QtWebChannel_include_dirs ${QtWebChannel_SOURCE_DIR} ${QtWebChannel_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5WebChannel_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebChannel_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtWebChannel_libraries pyside2 - ${Qt5WebChannel_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebChannel_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebChannel_deps QtCore) diff --git a/sources/pyside2/PySide2/QtWebEngine/CMakeLists.txt b/sources/pyside2/PySide2/QtWebEngine/CMakeLists.txt index 25e11d5d9..e1460ff21 100644 --- a/sources/pyside2/PySide2/QtWebEngine/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebEngine/CMakeLists.txt @@ -9,13 +9,13 @@ ${QtWebEngine_GEN_DIR}/qtwebengine_module_wrapper.cpp set(QtWebEngine_include_dirs ${QtWebEngine_SOURCE_DIR} ${QtWebEngine_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtWebEngine_libraries pyside2 - ${Qt5WebEngine_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebEngine_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebEngine_deps QtCore) create_pyside_module(NAME QtWebEngine diff --git a/sources/pyside2/PySide2/QtWebEngineCore/CMakeLists.txt b/sources/pyside2/PySide2/QtWebEngineCore/CMakeLists.txt index 74c112734..f0fb1eeda 100644 --- a/sources/pyside2/PySide2/QtWebEngineCore/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebEngineCore/CMakeLists.txt @@ -11,7 +11,8 @@ ${QtWebEngineCore_GEN_DIR}/qwebengineurlschemehandler_wrapper.cpp ${QtWebEngineCore_GEN_DIR}/qtwebenginecore_module_wrapper.cpp ) -if (Qt5WebEngineCore_VERSION VERSION_EQUAL 5.12.0 OR Qt5WebEngineCore_VERSION VERSION_GREATER 5.12.0) +if (Qt${QT_MAJOR_VERSION}WebEngineCore_VERSION VERSION_EQUAL 5.12.0 + OR Qt${QT_MAJOR_VERSION}WebEngineCore_VERSION VERSION_GREATER 5.12.0) list(APPEND QtWebEngineCore_SRC ${QtWebEngineCore_GEN_DIR}/qwebengineurlscheme_wrapper.cpp) endif() @@ -19,13 +20,13 @@ endif() set(QtWebEngineCore_include_dirs ${QtWebEngineCore_SOURCE_DIR} ${QtWebEngineCore_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtWebEngineCore_libraries pyside2 - ${Qt5WebEngineCore_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebEngineCore_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebEngineCore_deps QtCore) create_pyside_module(NAME QtWebEngineCore diff --git a/sources/pyside2/PySide2/QtWebEngineWidgets/CMakeLists.txt b/sources/pyside2/PySide2/QtWebEngineWidgets/CMakeLists.txt index 214ebc56b..b9fc1bc92 100644 --- a/sources/pyside2/PySide2/QtWebEngineWidgets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebEngineWidgets/CMakeLists.txt @@ -20,12 +20,12 @@ ${QtWebEngineWidgets_GEN_DIR}/qtwebenginewidgets_module_wrapper.cpp set(QtWebEngineWidgets_include_dirs ${QtWebEngineWidgets_SOURCE_DIR} ${QtWebEngineWidgets_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5WebChannel_INCLUDE_DIRS} - ${Qt5WebEngineWidgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebChannel_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebEngineWidgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -37,13 +37,13 @@ set(QtWebEngineWidgets_include_dirs ${QtPrintSupport_GEN_DIR} ) set(QtWebEngineWidgets_libraries pyside2 - ${Qt5WebEngineWidgets_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5WebChannel_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5PrintSupport_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebEngineWidgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebChannel_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}PrintSupport_LIBRARIES} ) set(QtWebEngineWidgets_deps QtGui QtWidgets QtNetwork QtWebChannel QtPrintSupport) create_pyside_module(NAME QtWebEngineWidgets diff --git a/sources/pyside2/PySide2/QtWebKit/CMakeLists.txt b/sources/pyside2/PySide2/QtWebKit/CMakeLists.txt index cc03b14b4..4220e46bf 100644 --- a/sources/pyside2/PySide2/QtWebKit/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebKit/CMakeLists.txt @@ -8,10 +8,10 @@ ${QtWebKit_GEN_DIR}/qtwebkit_module_wrapper.cpp set(QtWebKit_include_dirs ${QtWebKit_SOURCE_DIR} ${QtWebKit_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5WebKit_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebKit_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -19,10 +19,10 @@ set(QtWebKit_include_dirs ${QtWebKit_SOURCE_DIR} ${QtNetwork_GEN_DIR} ) set(QtWebKit_libraries pyside2 - ${Qt5WebKit_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebKit_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebKit_deps QtGui QtNetwork) create_pyside_module(NAME QtWebKit diff --git a/sources/pyside2/PySide2/QtWebKitWidgets/CMakeLists.txt b/sources/pyside2/PySide2/QtWebKitWidgets/CMakeLists.txt index 4ace240c0..0bf660a62 100644 --- a/sources/pyside2/PySide2/QtWebKitWidgets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebKitWidgets/CMakeLists.txt @@ -32,13 +32,13 @@ ${QtWebKitWidgets_GEN_DIR}/qtwebkitwidgets_module_wrapper.cpp set(QtWebKitWidgets_include_dirs ${QtWebKitWidgets_SOURCE_DIR} ${QtWebKitWidgets_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5WebKit_INCLUDE_DIRS} - ${Qt5PrintSupport_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5WebKitWidgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebKit_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}PrintSupport_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebKitWidgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -48,12 +48,12 @@ set(QtWebKitWidgets_include_dirs ${QtNetwork_GEN_DIR} ) set(QtWebKitWidgets_libraries pyside2 - ${Qt5WebKit_LIBRARIES} - ${Qt5WebKitWidgets_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebKit_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebKitWidgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebKitWidgets_deps QtWidgets QtPrintSupport QtNetwork) create_pyside_module(NAME QtWebKitWidgets diff --git a/sources/pyside2/PySide2/QtWebSockets/CMakeLists.txt b/sources/pyside2/PySide2/QtWebSockets/CMakeLists.txt index a28c633af..4a2c765a6 100644 --- a/sources/pyside2/PySide2/QtWebSockets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWebSockets/CMakeLists.txt @@ -12,18 +12,18 @@ ${QtWebSockets_GEN_DIR}/qtwebsockets_module_wrapper.cpp set(QtWebSockets_include_dirs ${QtWebSockets_SOURCE_DIR} ${QtWebSockets_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5WebSockets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WebSockets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtWebSockets_GEN_DIR} ${QtNetwork_GEN_DIR} ) set(QtWebSockets_libraries pyside2 - ${Qt5WebSockets_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}WebSockets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) set(QtWebSockets_deps QtNetwork) diff --git a/sources/pyside2/PySide2/QtWidgets/CMakeLists.txt b/sources/pyside2/PySide2/QtWidgets/CMakeLists.txt index 102c0ee14..506a6fc78 100644 --- a/sources/pyside2/PySide2/QtWidgets/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWidgets/CMakeLists.txt @@ -213,17 +213,17 @@ configure_file("${QtWidgets_SOURCE_DIR}/typesystem_widgets.xml.in" set(QtWidgets_include_dirs ${QtWidgets_SOURCE_DIR} ${QtWidgets_BINARY_DIR} ${pyside2_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ) set(QtWidgets_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} ) set(QtWidgets_deps QtGui) diff --git a/sources/pyside2/PySide2/QtWinExtras/CMakeLists.txt b/sources/pyside2/PySide2/QtWinExtras/CMakeLists.txt index 0e0b3d58b..3593394c3 100644 --- a/sources/pyside2/PySide2/QtWinExtras/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtWinExtras/CMakeLists.txt @@ -20,17 +20,17 @@ ${QtWinExtras_GEN_DIR}/qtwinextras_module_wrapper.cpp set(QtWinExtras_include_dirs ${QtWinExtras_SOURCE_DIR} ${QtWinExtras_BINARY_DIR} - ${Qt5WinExtras_INCLUDE_DIRS} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}WinExtras_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${libpyside_SOURCE_DIR}) set(QtWinExtras_libraries pyside2 - ${Qt5WinExtras_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}WinExtras_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtWinExtras_deps QtCore QtGui) diff --git a/sources/pyside2/PySide2/QtX11Extras/CMakeLists.txt b/sources/pyside2/PySide2/QtX11Extras/CMakeLists.txt index 8bc1a7ffd..9008da747 100644 --- a/sources/pyside2/PySide2/QtX11Extras/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtX11Extras/CMakeLists.txt @@ -11,17 +11,17 @@ configure_file("${QtX11Extras_SOURCE_DIR}/QtX11Extras_global.post.h.in" set(QtX11Extras_include_dirs ${QtX11Extras_SOURCE_DIR} ${QtX11Extras_BINARY_DIR} - ${Qt5X11Extras_INCLUDE_DIRS} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}X11Extras_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} ${libpyside_SOURCE_DIR}) set(QtX11Extras_libraries pyside2 - ${Qt5X11Extras_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}X11Extras_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) set(QtX11Extras_deps QtCore QtGui) diff --git a/sources/pyside2/PySide2/QtXml/CMakeLists.txt b/sources/pyside2/PySide2/QtXml/CMakeLists.txt index f17a77240..eb64b4795 100644 --- a/sources/pyside2/PySide2/QtXml/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtXml/CMakeLists.txt @@ -38,13 +38,13 @@ ${QtXml_GEN_DIR}/qtxml_module_wrapper.cpp set(QtXml_include_dirs ${QtXml_SOURCE_DIR} ${QtXml_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Xml_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Xml_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtXml_libraries pyside2 - ${Qt5Xml_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Xml_LIBRARIES}) set(QtXml_deps QtCore) create_pyside_module(NAME QtXml diff --git a/sources/pyside2/PySide2/QtXmlPatterns/CMakeLists.txt b/sources/pyside2/PySide2/QtXmlPatterns/CMakeLists.txt index 696c09c1a..adc1be516 100644 --- a/sources/pyside2/PySide2/QtXmlPatterns/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtXmlPatterns/CMakeLists.txt @@ -22,14 +22,14 @@ ${QtXmlPatterns_GEN_DIR}/qtxmlpatterns_module_wrapper.cpp set(QtXmlPatterns_include_dirs ${QtXmlPatterns_SOURCE_DIR} ${QtXmlPatterns_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5XmlPatterns_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}XmlPatterns_INCLUDE_DIRS} ${libpyside_SOURCE_DIR} ${QtCore_GEN_DIR} ) set(QtXmlPatterns_libraries pyside2 - ${Qt5Core_LIBRARIES} - ${Qt5XmlPatterns_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}XmlPatterns_LIBRARIES}) set(QtXmlPatterns_deps QtCore) create_pyside_module(NAME QtXmlPatterns diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp index 111e324b9..8bd2baac1 100644 --- a/sources/pyside2/PySide2/glue/qtcore.cpp +++ b/sources/pyside2/PySide2/glue/qtcore.cpp @@ -587,6 +587,14 @@ Py_END_ALLOW_THREADS PySide::runCleanupFunctions(); // @snippet moduleshutdown +// @snippet qt-qenum +%PYARG_0 = PySide::QEnum::QEnumMacro(%1, false); +// @snippet qt-qenum + +// @snippet qt-qflag +%PYARG_0 = PySide::QEnum::QEnumMacro(%1, true); +// @snippet qt-qflag + // @snippet qt-pysideinit Shiboken::Conversions::registerConverterName(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], "unicode"); Shiboken::Conversions::registerConverterName(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], "str"); @@ -1288,6 +1296,14 @@ QByteArray ba(1 + int(%2), char(0)); %CPPSELF.%FUNCTION_NAME(Shiboken::String::toCString(%PYARG_1), Shiboken::String::len(%PYARG_1)); // @snippet qcryptographichash-adddata +// @snippet qsocketdescriptor +#ifdef WIN32 +using DescriptorType = Qt::HANDLE; +#else +using DescriptorType = int; +#endif +// @snippet qsocketdescriptor + // @snippet qsocketnotifier PyObject *socket = %PYARG_1; if (socket != nullptr) { @@ -1689,11 +1705,19 @@ Py_END_ALLOW_THREADS // @snippet conversion-pyunicode #ifndef Py_LIMITED_API Py_UNICODE *unicode = PyUnicode_AS_UNICODE(%in); -# if defined(Py_UNICODE_WIDE) +# if defined(Py_UNICODE_WIDE) // cast as Py_UNICODE can be a different type -%out = QString::fromUcs4((const uint *)unicode); -# else -%out = QString::fromUtf16((const ushort *)unicode, PepUnicode_GetLength(%in)); +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +%out = QString::fromUcs4(reinterpret_cast<const char32_t *>(unicode)); +# else +%out = QString::fromUcs4(reinterpret_cast<const uint *>(unicode)); +# endif // Qt 6 +# else // Py_UNICODE_WIDE +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +%out = QString::fromUtf16(reinterpret_cast<const char16_t *>(unicode), PepUnicode_GetLength(%in)); +# else +%out = QString::fromUtf16(reinterpret_cast<const ushort *>(unicode), PepUnicode_GetLength(%in)); +# endif // Qt 6 # endif #else wchar_t *temp = PyUnicode_AsWideCharString(%in, NULL); diff --git a/sources/pyside2/cmake/Macros/FindQt5Extra.cmake b/sources/pyside2/cmake/Macros/FindQt5Extra.cmake index 6bfa5e074..71846e48a 100644 --- a/sources/pyside2/cmake/Macros/FindQt5Extra.cmake +++ b/sources/pyside2/cmake/Macros/FindQt5Extra.cmake @@ -4,9 +4,9 @@ # CT: maybe we can remove this. # For now, I just use the mapping to Qt5 -find_package(Qt5Multimedia) +find_package(Qt${QT_MAJOR_VERSION}Multimedia) -if (NOT Qt5Multimedia_FOUND) +if (NOT Qt${QT_MAJOR_VERSION}Multimedia_FOUND) find_path(QT_QTMULTIMEDIA_INCLUDE_DIR QtMultimedia PATHS ${QT_HEADERS_DIR}/QtMultimedia ${QT_LIBRARY_DIR}/QtMultimedia.framework/Headers diff --git a/sources/pyside2/cmake/Macros/PySideModules.cmake b/sources/pyside2/cmake/Macros/PySideModules.cmake index dca00ec11..14707f964 100644 --- a/sources/pyside2/cmake/Macros/PySideModules.cmake +++ b/sources/pyside2/cmake/Macros/PySideModules.cmake @@ -91,7 +91,10 @@ macro(create_pyside_module) list(REMOVE_DUPLICATES total_type_system_files) # Contains include directories to pass to shiboken's preprocessor. - set(shiboken_include_dirs ${pyside2_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}) + # Workaround: Added ${QT_INCLUDE_DIR}/QtCore until + # qtdeclarative/8d560d1bf0a747bf62f73fad6b6774095442d9d2 has reached qt5.git + string(REPLACE ";" ${PATH_SEP} core_includes "${Qt5Core_INCLUDE_DIRS}") + set(shiboken_include_dirs ${pyside2_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}${PATH_SEP}${core_includes}) set(shiboken_framework_include_dirs_option "") if(CMAKE_HOST_APPLE) set(shiboken_framework_include_dirs "${QT_FRAMEWORK_INCLUDE_DIR}") diff --git a/sources/pyside2/doc/CMakeLists.txt b/sources/pyside2/doc/CMakeLists.txt index 8eb4eca06..ffbb3c1eb 100644 --- a/sources/pyside2/doc/CMakeLists.txt +++ b/sources/pyside2/doc/CMakeLists.txt @@ -22,7 +22,7 @@ file(REMOVE ${CMAKE_CURRENT_LIST_DIR}/pyside.qdocconf ${CMAKE_CURRENT_LIST_DIR}/ # - Build include path for qdoc for shiboken # The last element of the include list is the mkspec directory containing qplatformdefs.h -list(GET Qt5Core_INCLUDE_DIRS -1 mkspecInclude) +list(GET Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS -1 mkspecInclude) configure_file("pyside-config.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf" @ONLY) file(READ "${pyside2_BINARY_DIR}/pyside2_global.h" docHeaderContents) @@ -56,8 +56,8 @@ foreach(moduleIn ${all_module_shortnames}) # -- @TODO fix this for macOS frameworks. file(APPEND "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf" " -I ${QT_INCLUDE_DIR}Qt${module} \\\n" - " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt5Core_VERSION} \\\n" - " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt5Core_VERSION}/Qt${module} \\\n") + " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION} \\\n" + " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION}/Qt${module} \\\n") if (${moduleIn} STREQUAL "X11Extras") set(globalHeader "QX11Info") @@ -95,16 +95,51 @@ add_custom_target(qdoc COMMENT "Running qdoc against Qt source code..." SOURCE "pyside.qdocconf") +# conditional tag for sphinx build +#string(JOIN "_" SPHINX_TAG ${DOC_OUTPUT_FORMAT} "format") +# Python script to replace the virtualFolder string in the QHP +set(py_cmd "from __future__ import print_function +import fileinput +import re +try: +\tfor line in fileinput.input('html/PySide.qhp',inplace=True,backup='.bak'): +\t\tline_copy=line.strip() +\t\tif not line_copy: # check for empty line +\t\t\tcontinue +\t\tmatch=re.match('(^.*virtualFolder.)doc(.*$)',line) +\t\tif match: +\t\t\trepl=''.join([match.group(1),'pyside2',match.group(2)]) +\t\t\tprint(line.replace(match.group(0),repl),end='') +\t\telse: +\t\t\tprint(line) +except: +\tpass\n") +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/py_script.py CONTENT ${py_cmd}) + add_custom_target(apidoc - COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b html ${CMAKE_CURRENT_BINARY_DIR}/rst html - #copying shiboken2 (including ApiExtractor) doc htmls - COMMENT "Copying over the Shiboken2 doc HTMLs..." - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/html/shiboken2 - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_BINARY_DIR}/../../shiboken2/doc/html - ${CMAKE_CURRENT_BINARY_DIR}/html/shiboken2 + COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} ${CMAKE_CURRENT_BINARY_DIR}/rst html + COMMENT "Generating PySide htmls..." ) +# create a custom commands to copy the shiboken docs +# and generate offline help based on the output format. +if(DOC_OUTPUT_FORMAT STREQUAL "html") + add_custom_command(TARGET apidoc POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/html/shiboken2 + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_BINARY_DIR}/../../shiboken2/doc/html + ${CMAKE_CURRENT_BINARY_DIR}/html/shiboken2 + COMMENT "Copying Shiboken docs..." + VERBATIM) +else() + file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/html/PySide.qhp QHP_FILE) + add_custom_command(TARGET apidoc POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} py_script.py + COMMAND qhelpgenerator ${QHP_FILE} + COMMENT "Generating QCH from a QHP file..." + VERBATIM) +endif() + # create conf.py based on conf.py.in configure_file("conf.py.in" "rst/conf.py" @ONLY) diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/domainindex.html b/sources/pyside2/doc/_themes/pysidedocs_qthelp/domainindex.html new file mode 100644 index 000000000..c136cdd1c --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/domainindex.html @@ -0,0 +1,57 @@ +{# + basic/domainindex.html + ~~~~~~~~~~~~~~~~~~~~~~ + + Template for domain indices (module index, ...). + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{% extends "layout.html" %} +{% set title = indextitle %} +{% block extrahead %} +{{ super() }} +{% if not embedded and collapse_index %} + <script type="text/javascript"> + DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true; + </script> +{% endif %} +{% endblock %} +{% block body %} +<div class="section"> + {%- set curr_group = 0 %} + + <h1>{{ indextitle }}</h1> + + <div class="modindex-jumpbox"> + {%- for (letter, entries) in content %} + <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> + {%- if not loop.last %} | {% endif %} + {%- endfor %} + </div> + + <table class="indextable modindextable" cellspacing="0" cellpadding="2"> + {%- for letter, entries in content %} + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap"><td></td><td><a name="cap-{{ letter }}"> + <strong>{{ letter }}</strong></a></td><td></td></tr> + {%- for (name, grouptype, page, anchor, extra, qualifier, description) + in entries %} + {%- if grouptype == 1 %}{% set curr_group = curr_group + 1 %}{% endif %} + <tr{% if grouptype == 2 %} class="cg-{{ curr_group }}"{% endif %}> + <td>{% if grouptype == 1 -%} + <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ curr_group }}" + class="toggler" style="display: none" alt="-" /> + {%- endif %}</td> + <td>{% if grouptype == 2 %} {% endif %} + {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%} + <tt class="xref">{{ name|e }}</tt> + {%- if page %}</a>{% endif %} + {%- if extra %} <em>({{ extra|e }})</em>{% endif -%} + </td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %} + <em>{{ description|e }}</em></td></tr> + {%- endfor %} + {%- endfor %} + </table> +</div> +{% endblock %} diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/fakebar.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/fakebar.png Binary files differnew file mode 100644 index 000000000..b45830e00 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/fakebar.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg Binary files differnew file mode 100644 index 000000000..cd474efba --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png Binary files differnew file mode 100644 index 000000000..3bc03b7c7 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/minus.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/minus.png Binary files differnew file mode 100644 index 000000000..da1c5620d --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/minus.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/plus.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/plus.png Binary files differnew file mode 100644 index 000000000..b3cb37425 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/plus.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pyside.css b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pyside.css new file mode 100644 index 000000000..aee5e4420 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pyside.css @@ -0,0 +1,1943 @@ +@import url('cookie-confirm.css') screen; + +/* -- admonitions -- */ + +div.admonition { + margin: 1.5em 0 1.5em; + padding: 0; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.admonition code { + font-family: inherit; +} + +p.admonition-title + p { + padding-left: 1em; +} + +div.admonition a:after { + content: ', '; +} + +div.admonition a:last-child:after { + content: ''; +} + +.body { + width: 100% +} +.bodywrapper .admonition p.admonition-title { + margin-bottom:5px +} + +.bodywrapper .admonition p { + margin:0 +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +div.warning, div.seealso, div.note { + padding: 6px 0px 6px 10px; + border: none; +} + +div.warning { + background-color: #ffe4e4; +} + +div.seealso { + background-color: #fff2d6; +} + +div.note { + background-color: #f3f3f4; +} + +table.docutils { + margin-right: auto; + margin-bottom: 10px; + border: none; + width: initial; +} + +table.docutils.colwidths-given td { + float: none; +} + +table.docutils th, +table.docutils td { + padding-left:0; + border: none; +} + +table.docutils td ul { + margin:0 +} + +table.docutils td ul > li { + margin: 0 0 0.5em; +} +h2 em { + float: right; + font-size: 10px; + position: relative; + top: -20px; +} + +.document { + padding-bottom: 20px; +} + +.documentwrapper { + margin-left: 20px; +} + +.body blockquote { + border: none; + padding-left: 0; + margin-bottom: 1.5em; +} + +.sphinxsidebar { + float: left; + width: 186px; + padding: 25px; + text-align: left; + background-color: #fff; +} + +.sphinxsidebar ul { + padding: 0px; + margin: 0px; + list-style-position: inside; +} + +.sphinxsidebar > ul { + padding: 0px; + margin: 0px; +} + +.sphinxsidebar ul li li { + margin-left: 10px; + padding: 0px; + font-size: 0.95em; +} + +.sphinxsidebar ul a, +.sphinxsidebar p.topless a { + word-break: break-word; +} + +.sphinxsidebar h3, .sphinxsidebar h3 a { + color: #333; +} + +.sphinxsidebar p.topless { + margin: 1em 0 1em; +} + +.pysidetoc ul { + list-style: none; + padding: 0px; + margin: 0px; +} + +.pysidetoc em { + font-style: normal; +} + +.pysidetoc strong { + display: block; + padding: 5px; + margin: 0 10px 10px 0; + border: none; + background-color: #e2e2e2; +} + +.section .docutils.container td { + float:left; +} + +.hide { + display: none; +} + +/* copy-notice */ +.document + p { + margin-left: 255px; + width: 70%; + font-size: 0.75em; + margin: 0 35px 15px 280px; +} + +#searchbox { + border-top: 1px solid #989898; + padding-top: 10px; + margin-left: -10px; + margin-right: -10px; + padding-left: 10px; + padding-right: 10px; +} + +#search_button { + border: 1px solid #3A393A; + background-color: #3A393A; + color: white; + cursor: pointer; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + +} + +form { + margin: 0px; + padding: 0px; +} + +#searchbox h3 { + padding: 10px 0 0 0; + margin-bottom: 5px; +} + +/* search field */ +form #q { + width: 136px; + /* height: 22px; */ + /* border: none; */ + margin: 0px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + margin-top: 2px; + padding: 4px; + line-height: 22px; +} + +#search-results h2 { + display: none; +} + +#search-results h2 { + display: none; +} + +#search-results ul.search { + margin: 0px; + padding: 0px; +} + +ul.search div.context { + padding-left: 40px; +} + +#installation td { + text-align: center; + font-weight: bold; +} + +em { + color: inherit; + font-style:italic; +} + +/******** REL bar *********/ + +.related { + display: inline; +} + +.related h3 { + display: none; +} + +.align-center { + text-align: center; +} + +.contentstable { + width: 100%; +} + +.contentstable td { + padding-left: 30px; + vertical-align: top; +} + +p.biglink a { + font-size: 20px; +} + +dt:target, .highlight { + background-color: #fbe54e; +} + +p.highlight-link { + margin-top: 10px; + font-size: 0.8em; +} + +#synopsis table, table.field-list { + margin: 1em 0 1em 0; +} + +table.field-list tr { + text-align: left; +} + +tt.descname { + font-size: 120%; + font-weight: bold; +} + +#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul { + margin: 0; + padding: 6px; + border: 1px solid #ddd; + border-radius: 0; + background-color: #e2e2e2; +} + +#functions p, #virtual-functions p, #slots p, #signals p, #static-functions p { + margin: 0; + padding: 0; +} + +#functions li, #virtual-functions li, #slots li, #signals li, #static-functions li { + list-style: none; + margin: 5px; + padding: 0; + font-size: 90%; +} + +#synopsis span.pre { + color: #009491; + font-weight: bolder; +} + +#detailed-description .class dt, +#detailed-description .method dt, +#detailed-description .staticmethod dt, +#detailed-description .attribute dt { + margin: 0px; + margin-bottom: 10px; + padding: 10px; + font-weight: bold; + background-color: #e2e2e2; + border: none; + border-radius: 0; +} + +#detailed-description dd > blockquote, +#detailed-description dd > .field-list { + font-family: monospace; + font-size: small; + border-left: 10px solid #e2e2e2; + padding-left: 10px; + margin-bottom: 1.5em; +} + +#detailed-description dd > blockquote blockquote { + border: none; + padding: 0; +} + +#detailed-description .class .field-odd, +#detailed-description .method .field-odd, +#detailed-description .staticmethod .field-odd, +#detailed-description .attribute .field-odd { + margin: 0; + padding: 1px 0 0 0; + background-color: #ffffff; + +} + +#detailed-description .class .field-even, +#detailed-description .method .field-even, +#detailed-description .staticmethod .field-even, +#detailed-description .attribute .field-even { + margin: 0; + padding: 1px 0 0 0; + background-color: #ffffff; +} + +#detailed-description .class .field-odd li, +#detailed-description .method .field-odd li, +#detailed-description .staticmethod .field-odd li, +#detailed-description .attribute .field-odd li { + list-style: none; + margin: 0; + padding: 0; + +} + +#detailed-description .class .field-even li, +#detailed-description .method .field-even li, +#detailed-description .staticmethod .field-even li, +#detailed-description .attribute .field-even li { + list-style: none; + margin: 0; + padding: 0; +} + +#detailed-description .class .field-odd p, +#detailed-description .method .field-odd p, +#detailed-description .staticmethod .field-odd p, +#detailed-description .attribute .field-odd p{ + margin: 0; + margin-left: 20px; + +} + +#detailed-description .class .field-even p, +#detailed-description .method .field-even p, +#detailed-description .staticmethod .field-even p, +#detailed-description .attribute .field-even p{ + margin: 0; + margin-left: 20px; +} + +#detailed-description .class .field-odd p:last-child, +#detailed-description .method .field-odd p:last-child, +#detailed-description .staticmethod .field-odd p:last-child, +#detailed-description .attribute .field-odd p:last-child { + margin-bottom: 10px; + +} + +#detailed-description .class .field-even p:last-child, +#detailed-description .method .field-even p:last-child, +#detailed-description .staticmethod .field-even p:last-child, +#detailed-description .attribute .field-even p:last-child{ + margin-bottom: 10px; +} + +.document dl.attribute, +.document dl.class, +.document dl.method, +.document dl.staticmethod { + margin-top: 2em; +} + +.document dl.attribute dd, +.document dl.class dd, +.document dl.method dd, +.document dl.staticmethod dd { + padding-left: 1em; +} + +#detailed-description .attribute td:nth-child(1) { + font-family: monospace; +} + +/* Qt theme */ +#navbar { + position:fixed; + top:0; + left:0; + z-index:100; + background:#fff; + width:100% +} +#navbar .container, .fixed .container { + max-width:1280px; + margin:0 auto; + padding:0 3.9%; /* 0? */ + position:relative; + overflow:visible +} +#navbar .navbar-header { + position:relative +} +#menuextras li a:hover span { + color: #41cd52; +} +/* new header */ +#mm-wrap, #mm-wrap #mm-helper, +#mm-wrap #mm-helper li.mm-item, +#mm-wrap #mm-helper a.mm-link { + -moz-transition: none; + -o-transition: none; + -webkit-transition: none; + transition: none; + -webkit-border-radius: 0 0 0 0; + -moz-border-radius: 0 0 0 0; + -ms-border-radius: 0 0 0 0; + -o-border-radius: 0 0 0 0; + border-radius: 0 0 0 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + -ms-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; + background: none; + border: 0; + bottom: auto; + box-sizing: border-box; + clip: auto; + color: #090e21; + display: block; + float: none; + font-family: inherit; + font-size: 14px; + height: auto; + left: auto; + line-height: 1.7; + list-style-type: none; + margin: 0; + min-height: 0; + opacity: 1; + outline: none; + overflow: visible; + padding: 0; + position: relative; + right: auto; + text-align: left; + text-decoration: none; + text-transform: none; + top: auto; + vertical-align: baseline; + visibility: inherit; + width: auto; +} +#mm-wrap #mm-helper { + visibility:visible; + text-align:right; + padding:0 0px 0 0px +} +#navbar #mm-wrap #mm-helper li.mm-item { + border-right:solid #f3f3f4 1px; + padding-right:30px; + padding-left:30px +} +#navbar #mm-wrap #mm-helper li.mm-item > a:hover { + opacity: .5 +} +#mm-wrap #mm-helper > li.mm-item { + margin:0 0 0 0; + display:inline-block; + height:auto; + vertical-align:middle +} +#navbar #mm-wrap #mm-helper li.mm-item:nth-child(3) { + border-right:0 +} +#mm-wrap #mm-helper a.mm-link { + cursor: pointer +} +@media (max-width: 1279px) { + #navbar { + padding:0; + position:relative; + } + #navbar .container { + max-width:100% + } + .container { + padding:0 2% + } +} +#navbar .navbar-oneQt { + display:inline; + float:left; + width:31px; + color:#41cd52 +} +#navbar .navbar-oneQt:before { + content:attr(data-icon); + position:absolute; + top:14px; + left:0; + color:#41cd52; + font-family:'Qt Icons'; + line-height:1; + font-size:40px; + transition:all 0.3s ease-in-out; +} +#mm-wrap { + clear:both; + background:rgba(255, 255, 255, 0.1); + -webkit-border-radius:0px 0px 0px 0px; + -moz-border-radius:0px 0px 0px 0px; + -ms-border-radius:0px 0px 0px 0px; + -o-border-radius:0px 0px 0px 0px; + border-radius:0px 0px 0px 0px +} +#mm-wrap #mm-helper li.mm-item:last-child a { + background:transparent url("icon_avatar.png") 50% 50% no-repeat !important; + background-size:24px !important; + width:24px !important; + height:24px !important; +} +#navbar #mm-wrap #mm-helper li.mm-item > a { + opacity:1; + -webkit-transition:all 0.3s ease-in-out; + -moz-transition:all 0.3s ease-in-out; + -ms-transition:all 0.3s ease-in-out; + -o-transition:all 0.3s ease-in-out; + transition:all 0.3s ease-in-out; +} +#mm-wrap #mm-helper > li.mm-item > a.mm-link { + border-top:0px solid #fff; + border-left:0px solid #fff; + border-right:0px solid #fff; + border-bottom:0px solid #fff; + outline:none; + text-decoration:none; + padding:0 0 0 0; + line-height:70px; + font-weight:normal; + height:70px; + vertical-align:baseline; + text-align:left; + width:auto; + display:block; + color:#090e21; + text-transform:none; + text-decoration:none; + background:rgba(0, 0, 0, 0); + -webkit-border-radius:0px 0px 0px 0px; + -moz-border-radius:0px 0px 0px 0px; + -ms-border-radius:0px 0px 0px 0px; + -o-border-radius:0px 0px 0px 0px; + border-radius:0px 0px 0px 0px; + font-family:inherit; + font-size:14px; +} +/* end new header */ +@media (min-width: 1320px) { + .body .flowListDiv dl.flowList { + -webkit-column-count:3; + -moz-column-count:3; + column-count:3 + } +} +@media (min-width: 1120px) { + #navbar.fixed { + -moz-box-shadow:0px 0px 8px rgba(0,0,0,0.23); + -webkit-box-shadow:0px 0px 8px rgba(0,0,0,0.23); + box-shadow:0px 0px 8px rgba(0,0,0,0.23) + } + #navbar.fixed #mm-wrap #mm-helper > li.mm-item > a.mm-link { + height:50px; + line-height:50px + } + #navbar.fixed .navbar-oneQt:before { + font-size:35px; + top:7px + } + + .flowListDiv dl.flowList { + -webkit-column-count:2; + -moz-column-count:2; + column-count:2 + } +} +@media (max-width: 1120px) { + #navbar { + padding:0; + position:relative + } + #navbar .navbar-oneQt:before { + left:10px + } + #navbar .container { + max-width:100%; + padding:0 + } + #footerbar .container { + padding:0 + } + body .main { + margin-top:0px + } + #footerbar .footer-main .footer-nav { + padding:3.9% 0 3.9% 3%; + border-bottom:1px solid #413d3b; + float:none; + display:block; + width:auto + } + #footerbar .footer-main .theqtcompany { + clear:both; + float:left; + margin:30px 0 8px 3% + } + #footerbar .footer-main .footer-social { + float:left; + padding:50px 0px 0px 3% + } + #footerbar #menu-footer-submenu { + clear:both; + float:none; + display:block; + padding:0px 0px 3.9% 3% + } + ul#menu-footer-submenu { + margin-left: 0 + } +} +.cookies_yum { + background-color:#cecfd5; + display:none; + width:100% +} +.cookies_yum img { + width:25px; + top:6px; + display:inline-block; + position:absolute; + left:13px +} +.cookies_yum div { + margin:0 auto; + max-width:1280px; + min-height:30px; + padding:6px 0px 6px 0px; + position:relative +} +.cookies_yum p { + color:#09102b; + margin:0px; + font-size:0.79em; + display:inline-block; + line-height:1.2; + padding:0 30px 0 50px +} +.cookies_yum p a { + white-space:nowrap +} +.cookies_yum a:hover { + color:#46a2da +} +.cookies_yum .close { + width:15px; + height:15px; + background-image:url("cookiebar-x.png"); + background-size:15px 30px; + background-position:top left; + cursor:pointer; + top:13px; + right:13px; + position:absolute; + transition:none +} +.cookies_yum .close:hover { + background-position:bottom left +} +#sidebar-toggle,#toc-toggle { + width:24px; + height:14px; + background-size:24px 28px; + cursor:pointer; + background-image:url("list_expand.png"); + float:right +} +#sidebar-toggle.collapsed, +#toc-toggle.collapsed { + background-position:bottom left +} +#sidebar-content > h2 { + display:none +} +#footerbar { + background:#222840; + color:#fff; + font-size: 0.9em; +} +#footerbar.fixed { + bottom:0; + left:0; + width:100% +} +#footerbar .footer-nav { + display:inline; + float:left +} +#footerbar .footer-main .footer-nav li { + float:left; + margin-right:1em +} +#footerbar .footer-main .footer-nav li a { + display:block; + padding:30px 0 10px 0; + line-height:20px; + height:20px; + color:#fff; + font-weight: 600; +} +#footerbar .footer-main .footer-nav li a:hover,#footerbar .footer-main .footer-nav li.current-menu-item a { + color:#eee +} +#footerbar .footer-main .footer-nav .sub-menu { + margin-left:0; + margin-bottom:0 +} +#footerbar .footer-main .footer-nav .sub-menu li { + float:none; + width: 100%; +} +#footerbar .footer-main .footer-nav .sub-menu ul { + padding:1px 1em; + font-size:0.786em; + line-height:8px; + float:none; + color:#5d5b59; + margin-bottom:0 +} +#footerbar .footer-main .footer-nav .sub-menu li a { + padding:2px 0; + font-size:1em; + float:none; + color:#cecfd5; + font-weight: 400; +} +#footerbar .footer-main .footer-nav .sub-menu li a:hover,#footerbar .footer-main .footer-nav .sub-menu li.current-menu-item a { + color:#eee +} +#footerbar .theqtcompany { + background:url("theqtcompany.png") no-repeat; + background-size:100%; + width:215px; + height:68px; + display:inline; + float:right; + margin:29px 0 28px 30px +} +#footerbar .footer-social { + display:inline; + float:right; + width:164px +} +#footerbar .footer-main .footer-social>div { + margin-left:0.1em; + margin-bottom:10px +} +#footerbar .disclaimer { + font-size:0.786em; + line-height:2.73; + color:#868584; + padding-top:20px; + padding-bottom:0.5% +} +#footerbar .disclaimer a { + color:#bdbebf +} +#footerbar .disclaimer a:hover { + color:#d6d6d6 +} +#footerbar .disclaimer ul li { + float:left; + vertical-align:middle; + margin-left:1.18em +} +#footerbar .disclaimer ul li:first-child { + margin-left:0 +} +#footerbar .disclaimer ul.lang-selector a { + color:#506a34; + color:rgba(128,195,66,0.3) +} +#footerbar .disclaimer ul.lang-selector a:hover { + color:#80c342; + color:rgba(128,195,66,0.7) +} +#menu-footer-menu, #menu-footer-menu ul { + margin-left:0; + margin-bottom:0 +} +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 400; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot"); + /* IE9 Compat Modes */ + src: local("Titillium Web"), local("TitilliumWeb-Regular"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +/* titillium-web-italic - latin_latin-ext */ +@font-face { + font-family: 'Titillium Web'; + font-style: italic; + font-weight: 400; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot"); + /* IE9 Compat Modes */ + src: local("Titillium WebItalic"), local("TitilliumWeb-Italic"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +/* titillium-web-600 - latin_latin-ext */ +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 600; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot"); + /* IE9 Compat Modes */ + src: local("Titillium WebSemiBold"), local("TitilliumWeb-SemiBold"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +@font-face { + font-family:monospace; + font-style:normal; + font-weight:400; + src:local("Droid Sans Mono"),local("DroidSansMono"),url(//fonts.gstatic.com/s/droidsansmono/v7/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff) format("woff") +} +@font-face { + font-family:'Qt Icons'; + src:url("../style/icomoon.eot?-tgjuoj"); + src:url("../style/icomoon.eot?#iefix-tgjuoj") format("embedded-opentype"),url("../style/icomoon.woff?-tgjuoj") format("woff"),url("../style/icomoon.ttf?-tgjuoj") format("truetype"),url("../style/icomoon.svg?-tgjuoj#icomoon") format("svg"); + font-weight:normal; + font-style:normal +} +@font-face { + font-family:'social-icons'; + src:url("../style/social-icons.eot?54625607"); + src:url("../style/social-icons.eot?54625607#iefix") format("embedded-opentype"), + url("../style/social-icons.woff?54625607") format("woff"); + font-weight:normal; + font-style:normal +} +.clearfix:before,.clearfix:after { + content:" "; + display:table +} +.clearfix:after { + clear:both +} +.clearfix { + *zoom:1 +} +.clearfix .right { + float:right +} +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { + margin:0; + padding:0; + border:0; + font-size:100%; + line-height: 1.4; +} +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { + vertical-align:baseline +} +h1,h2,h3,h4,h5,h6 { + font-weight:300 +} +.body h2,.body h3,.body h4,.body h5,.body h6 { + margin:1.5em 0 0.75em +} +.body h1 { + margin-bottom:0.75em; + font-size:2.25em; +} +.body h3.fn,.body h3.flags { + color:#26282a; + font-size:1.46em; + padding:15px 0 15px 0; + border-bottom:2px #eee solid; + word-wrap:break-word +} +.body .fngroup { + border-bottom:2px #eee solid; + padding-bottom:15px; + margin-bottom:1.5em +} +.body .fngroup h3.fngroupitem { + margin:0; + padding-bottom:0; + border:none +} +.body h3.fn .name, +.body h3 span.type, +.qmlname span.name { + font-weight: 400 +} +.qmlname { + font-size:1.46em +} +.qmlproto table { + border:none; + border-bottom:2px #eee solid +} +.qmlproto table p { + max-width:100% +} +.qmlproto table tr { + background-color:#fff +} +.qmlname td, .qmlname th { + border:none; + text-align:left; + padding:5px 0 0 0 +} +.qmlreadonly,.qmldefault { + padding:0 5px 0 5px; + font-size:0.75em; + background-color:#eee; + float:right +} +.qmlreadonly { + color:#414141 +} +.qmldefault { + color:#D14141 +} +.rightAlign { + padding:3px 5px 3px 10px; + text-align:right +} +.centerAlign.functionIndex { + text-align:center; + font-size:150%; + margin-bottom: 1em +} +article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { + display:block +} +body { + line-height:1.25em; + font-family: Arial, Helvitica; + font-weight:400; + transition-duration:1s; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 16px; + background-color:#f3f3f4; + color:#404244; +} +ol,ul { + list-style-type: square; + #color: #17a81a; +} +.body ol,.body ul { + margin-top:0.75em; + margin-left:20px +} +.bodywrapper ol>li { + list-style-type:decimal; + margin-left:15px +} +.bodywrapper ol.a >li { + list-style-type:lower-alpha; +} +.bodywrapper ol.A >li { + list-style-type:upper-alpha; +} +.bodywrapper ol.i >li { + list-style-type:lower-roman; +} +.bodywrapper ol.I >li { + list-style-type:upper-roman; +} +.body li p { + margin-top:1em +} +blockquote,q { + quotes:none; + border-left:10px solid #ddd; + padding-left:10px +} +blockquote:before,blockquote:after,q:before,q:after { + content:''; + content:none; + width:100% +} +table { + border-collapse:collapse; + border-spacing:0; + margin-bottom:5px; + width:100% +} +a { + color:#17a81a; + text-decoration:none; + transition-duration:0.3s +} +a:hover { + color:#17a81a +} +.main,#footerbar>div { + max-width:1280px; + width:95%; + margin:0 auto +} +.main { + margin-top:80px +} +@media (max-width: 1120px) { + .main,.navbar-header,#footerbar>div { + width: 100%; + margin: 0; + } + .main .main-rounded { + padding: 0 15px; + } +} +.main_index { + background-color:#fff +} +.sectionlist { + margin-bottom:2em +} +[class*="col-"] { + letter-spacing:normal +} +.landing,.main_index .row { + letter-spacing:-0.31em +} +.main_index .row>div { + letter-spacing:normal +} +.col-1,.body { + display:inline-block; + background-color:#fff; + padding: 25px 35px 20px 30px; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; +} +.col-1 h2 { + font-size:1.8em; + font-weight:300; + line-height:1.1; + margin-bottom:0.83em; + margin-top:1em +} +.icons1of3 img { + display:inline-block; + float:left; + margin-right:0.75em; + margin-top:-5px; + width:2.75em +} +div.multi-column { + position:relative +} +div.multi-column div { + display:-moz-inline-box; + display:inline-block; + vertical-align:top; + margin-top:1em; + margin-right:2em; + width:16em +} +.sidebar { + display:block; + position:relative; + position:sticky; + float:left; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + width:20%; + padding-right:20px +} +.sidebar li { + text-overflow:ellipsis; + overflow:hidden +} +.toc,.sectionlist { + padding:25px; + background-color:#fff; + margin-bottom:1.25em +} +.sidebar .sectionlist p { + margin-bottom:0 +} +.sectionlist.promo { + padding:0; + background-color:#f3f3f4 +} +.sidebar-content:empty { + display:none; + visibility:hidden +} +.col-2 h2,.toc h3,.sidebar-content h2, +.sidebar-content h3,.sectionlist h2, +.sphinxsidebar { + position: fixed; + overflow: scroll; + overflow-x: hidden; + overflow-y: hidden; +} +.sphinxsidebar h3 { + font-weight: bold; + margin-bottom:1em; +} +.toc h3 a { + color:#404244 +} +.title { + font-size:2.25em; + font-weight:300; + letter-spacing:-1px; + line-height:1.15em; + margin-bottom:0.5em; + word-wrap:break-word +} +.navigationbar,col-1 h2 { + font-size:0.85em +} +.navigationbar h1 { + font-size:2.5em; + margin-bottom:0.85em; + margin-top:0.85em +} +.navigationbar li { + display:inline-block; + margin-right:5px; + position:relative; + padding-right:10px; + color:#585a5c +} +.navigationbar ul:last-of-type li a { + color:#404244 +} +.sectionlist li, .sphinxsidebar li { + padding-bottom: 10px; + line-height: 1.75em; +} +.col-1 ul { + margin-bottom:1.56em +} +.bodywrapper li { + margin-top:0.5em; + line-height:1.25em +} +.bodywrapper li.level2 { + margin-left:10px; + margin-top:0.4em; + font-size:0.9375em; +} +.bodywrapper p, +.bodywrapper dd { + line-height:1.25em; + margin:1em 0 1em; + color:#404244 +} +.bodywrapper b { + font-weight:600 +} +.body ul,.body ol { + /* margin-bottom:1.5em */ +} +.bodywrapper ul ul { + margin-top:0.5em +} +.bodywrapper .naviNextPrevious { + margin-top:25px; + max-width:100% +} +.naviNextPrevious.headerNavi, +p.naviNextPrevious + p { + display:none +} +.nextPage { + float:right +} +.prevPage:before { + content:"< " +} +.nextPage:after { + content:" >" +} +.navigationbar li a { + color:#404244 +} +.navigationbar li:after { + color:#404244; + content:"›"; + display:inline-block; + font-size:1.5em; + line-height:1; + position:absolute; + right:-2px; + top:-4px +} +.sub-navigation { + margin-top:10px +} +.navigationbar li:last-child:after,.sub-navigation li:after { + content:none +} +.navigationbar { + margin-bottom:10px; + line-height:1em +} +#buildversion { + margin-bottom:10px; + font-style:italic; + font-size:small; + float:right +} +.copy-notice { + width:75%; + font-size:0.75em; + margin:20px 35px 0 10px; + line-height:1.75em; + float:right; + color:#585a5c +} +.copy-notice.index { + margin-top:10px; + float:none +} +li a.active { + color:#585a5c +} +.flowList { + padding:25px +} +.flowListDiv dl { + -webkit-column-count:1; + -moz-column-count:1; + column-count:1 +} +.flowList dd { + display:inline-block; + margin-left:10px; + width:90%; + line-height:1.15em; + overflow-x:hidden; + text-overflow:ellipsis +} +.alphaChar { + font-size:2em; + position:absolute +} +.flowList.odd { + background-color:#f9f9f9 +} +.body ul>li,.doc-column ul>li { + list-style-image:url("list_arrow.png"); + margin-left:15px; + color:#404244; + margin-top:0.65em; + line-height:1em +} +.bodywrapper table p { + margin:0px; + padding:0px +} +.bodywrapper table p { + margin:0px; + padding:0px; + min-height:1.25em +} +.bodywrapper .qmldoc { + margin-top:0.75em +} +.body h2 { + margin-top: 1.5em; + font-size:1.75em +} +.body h3 { + font-size:1.35em +} +.body h4 { + font-size:1.15em +} +.body p img { + margin-top:0.75em; + max-width:100% +} +.body .border img { + box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5) +} +.body .border .player { + box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5) +} +.body p.figCaption { + transform:translateY(-30px); + color:#606366; + font-size:95%; + margin-left:3px; + font-style:italic +} +.body table { + width:initial; + vertical-align:initial +} +table .odd { + background-color:#f9f9f9 +} +table thead { + text-align:left; + padding-left:20px +} +table,table td,table th { + border:1px solid #eee +} +table td,table th { + padding:5px 20px; + line-height:1.3 +} +.body .fixed table td { + min-width:50%; + width:50% +} +table.alignedsummary,table.propsummary { + width:initial +} +table.valuelist td.tblval { + font-size:0.75em +} +div.main_index .row { + border-bottom:10px solid #f3f3f4 +} +div.main_index .row { + position:relative +} +div.main_index .row>div { + display:inline-block; + width:50%; + vertical-align:top; + padding:2em 3em; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box +} +div.main_index h2 { + font-size:2.1875em; + margin-bottom:1em +} +#search_bar { + width:40%; + float:right +} +div.main_index .row:after { + content:""; + position:absolute; + top:0; + right:50%; + height:100%; + width:10px; + background-color:#f3f3f4 +} +div.table { + overflow-x:auto +} +.body tr > td > pre { + font-size:0.75em +} +p.qt_commercial { + border:3px solid #5caa15; + margin:0 auto; + padding:15px; + width:28%; + text-align:center; + clear:both +} +h1.qt_commercial { + padding:20px; + background-color:#5caa15; + display:inline; + float:right; + font-size:1.25em; + line-height:1.25em; + height:1.25em; + color:#fff +} +div.qt_commercial { + border-top:5px solid #5caa15; + margin-bottom:50px +} +div.pre { + position:relative; + height:auto +} +pre, .LegaleseLeft { + background-color:#222840; + color:#fff; + display:block; + font-family:monospace; + line-height:1.5; + overflow-x:auto; + margin-bottom:25px; + padding:25px; + margin-top:0.75em; + font-size: .8em; +} +.bodywrapper .LegaleseLeft p { + color:#fff; + white-space: pre-wrap +} +pre .str,code .str { + color:#aaaaaa +} +pre .kwd,code .kwd { + color:#ffff55 +} +pre .com,code .com { + color:#55ffff +} +pre .typ,code .typ { + color:#4f9d08 +} +pre a .typ,code a .typ { + color:#21be2b +} +pre .lit,code .lit { + color:#ff55ff +} +pre .pun,code .pun { + color:#fff +} +pre .pln,code .pln { + color:#fff +} +@media print { + pre { + background-color:#eee !important + } + pre .str,code .str { + color:#060 + } + pre .kwd,code .kwd{ + color:#006; + font-weight:bold + } + pre .com,code .com { + color:#600 + } + pre .typ,code .typ { + color:#404; + font-weight:bold + } + pre .lit,code .lit { + color:#044 + } + pre .pun,code .pun { + color:#440 + } + pre .pln,code .pln { + color:#000 + } +} +pre.wrap { + white-space:pre-wrap +} +pre span.wrap { + display:none; + background:url("wrap.png") no-repeat; + right:0; + top:2px; + position:absolute; + width:20px; + height:14px; + margin:4px; + opacity:0.65 +} + +span.pre { + color: #09102d; +} + +span.wrap:hover { + opacity:1 +} +span.wrap:active { + opacity:0.75 +} +.copy_text { + background-color:#46a2da; + color:#fff; + border:2px solid #46a2da; + padding:10px 16px; + margin-left:-10px; + margin-top:-50px; + position:absolute; + opacity:0; + cursor:pointer; + float:right +} +.copy_text:hover { + background-color:#fff; + color:#46a2da +} +code,.codelike { + font-family:monospace; +} +#detailed-description .function dt > code, +#detailed-description .function dt > em { + font-weight:bold +} +h3.fn code { + font-size:0.75em; + float:right; + background-color:#eee; + padding:3px; + margin: 3px 0 0 20px +} +pre:hover>.copy_text { + display:inline-block; + opacity:1; + transition:0.5s ease +} +#main_title_bar { + background:url("pyside-logo.png") no-repeat; + background-size:100%; + width:366px; + height:86px; + margin:15px 0 15px 0 +} +#main_title_bar h1 { + visibility:hidden +} +#main_title_bar .search_bar { + letter-spacing:normal; + width:50%; + display:inline-block; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + vertical-align:middle +} +#main_title_bar h1 { + letter-spacing:normal; + display:inline-block; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + vertical-align:middle +} +#main_title_bar .search_bar * { + letter-spacing:normal; + padding:0; + margin:0; + border:none +} +#sidebar-toggle,#toc-toggle { + display:none +} +@media (max-width: 980px) { + body { + font-size:calc-em(14px) + } + #main_title_bar>h1,#main_title_bar .search_bar { + width:100% + } + #main_title_bar .search_bar { + margin-bottom:15px + } + .main { + margin-top:0px + } + .main_index .row { + border:none !important + } + .title { + font-size:1.5em; + font-weight:400; + word-wrap:break-word + } + .col-1,.body,.naviNextPrevious,.sidebar { + padding:10px + } + .sidebar { + position:relative; + padding-top:0 + } + .search .sidebar { + display:none; + visibility:hidden + } + .col-2 h2,.toc h3,.sidebar-content h2,.sidebar-content h3,.sectionlist h2 { + text-align:center; + margin-bottom:5px + } + div.main_index .row:after { + content:none + } + div.main_index .row>div { + display:block !important; + width:100%; + padding:15px; + margin:0 + } + .body,.sidebar,.col-1 { + width:100% + } + .sidebar-content,.col-2,.toc { + background-color:#fff; + margin-bottom:1em; + padding:20px + } + #sidebar-toggle,#toc-toggle { + display:block + } + #sidebar-toggle.collapsed + h2 { + display:block + } + .bodywrapper p { + margin-bottom:1em; + max-width:100% + } + table td,table th { + padding:5px 5px + } + .sectionlist { + padding:0 + } + .sidebar > .sectionlist { + padding:20px + } + .sectionlist.promo { + max-width:46%; + margin:0 auto 1em auto; + float:left; + padding:0 2% + } + .sidebar .sidebar-content { + clear:both + } + .copy-notice { + float:none; + width:initial + } +} +[id]:target > *:first-child, +dt[id]:target { + -webkit-animation:highlighter 3s; + animation:highlighter 3s +} +@-webkit-keyframes highlighter { + 25% { + background-color:#d1e8f6; + color:#444 + } + 75% { + background-color:#d1e8f6; + color:#444 + } +} +@keyframes highlighter { + 25% { + background-color:#d1e8f6; + color:#444 + } + 75% { + background-color:#d1e8f6; + color:#444 + } +} +@-webkit-keyframes copypaste { + 25% { + opacity:1 + } + 100% { + border-radius:10px; + margin-top:-50px; + opacity:1 + } +} +@keyframes copypaste { + 25% { + opacity:1 + } + 100% { + border-radius:10px; + margin-top:-50px; + opacity:1 + } +} +#footer { + clear:both +} +.footer-social i { + font-family: "social-icons"; + font-style: normal; + font-size:150%; + margin: .55em; + color: #cecfd5 +} +.footer-social i:hover { + color: #eee +} +.footer-social .icon-twitter:before { + content: '\f099' +} +.footer-social .icon-facebook:before { + content: '\f09a' +} +.footer-social .icon-youtube:before { + content: '\f16a' +} +.menuextraslanguages { + display:none; + visibility:hidden +} + +input:focus { + border-color: #46a2da; + box-shadow: 0 0 5px #46a2da; + color: #000; +} + +.animation { + width: 100%; + border-style: none; + border-width: 0 +} + +.player { + width: auto; + position: relative; + display: table; + margin-bottom:1.5em; +} + +.playcontrol { + display: none; + background: url("play_icon.svg") no-repeat center, + linear-gradient( + rgba(0,0,0,0.15), rgba(0,0,0,0.15) + ); + background-size: 25%; + width: 100%; + height: 100%; + position: absolute; + left: 0%; + right: 0%; + top: 0%; + bottom: 0%; + margin: auto +} + +/* expand/collapse code sections */ +pre input { + display:none; + visibility:hidden +} +pre label { + display:block; + margin:-3px 3px 0 -16px; + text-align:center; + color:#21be2b; + float:left; +} +pre label:hover { + color:#fff +} +pre label::before { + font-weight:600; + font-size:16px; + content:"+"; + display:inline-block; + width:16px; + height:16px +} +#ec_expand { + height:16px; + overflow:hidden; + transition:height 0.35s; +} +#ec_expand::before { + content:"...*/"; + color:#aaa; + background-color:#3a4055; + z-index:99 !important; + right:25px; + position:absolute +} +#ec_toggle:checked ~ #ec_expand { + height:initial +} +#ec_toggle:checked ~ #ec_expand::before { + content:"" +} +#ec_toggle:checked ~ label::before { + content:"-" +} + +/* permalinks */ +h1:hover > .headerlink, +h2:hover > .plink, +h2:hover > .headerlink, +h3:hover > .plink, +h3:hover > .headerlink, +h4:hover > .plink, +h4:hover > .headerlink, +h5:hover > .plink, +h5:hover > .headerlink { + opacity:1 +} +a.plink, a.headerlink { + opacity: 0; + padding-left: 8px; + font-size: 0.8em; + font-weight: 600; + transition: opacity 180ms ease-in-out +} +a.plink::before { + content:'\00B6' +} + +table.special { + border: 3px; + padding: 0px; + border-collapse: separate; + border-spacing: 20px; + line-height: 1.5em; +} + +.special p { + text-align: center; + color: #3a4055; +} + +.special a { + display: block; + border-bottom: 0; + text-decoration: none; +} + +.special a:hover { + border-bottom: 0; + text-decoration: none; +} + +.special strong { + color: #17a81a; + font-size: 110%; + font-weight: normal; +} + +table.special th, +table.special td { + border: 1px solid #888; + padding-top: 14px; + padding-bottom: 14px; + padding-left: 6px; + padding-right: 5px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} + +.special td:hover { + padding-top: 2px; + padding-bottom: 2px; + border-bottom: 4px solid #41cd52; +} diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png Binary files differnew file mode 100644 index 000000000..3a2f2bd17 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png Binary files differnew file mode 100644 index 000000000..4036733a7 --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png diff --git a/sources/pyside2/doc/_themes/pysidedocs_qthelp/theme.conf b/sources/pyside2/doc/_themes/pysidedocs_qthelp/theme.conf new file mode 100644 index 000000000..4384b459c --- /dev/null +++ b/sources/pyside2/doc/_themes/pysidedocs_qthelp/theme.conf @@ -0,0 +1,7 @@ +[theme] +inherit = default +stylesheet = pyside.css +pygments_style = none + +[options] +nosidebar = true diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/clipboard/clipwindow.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/clipboard/clipwindow.py index 726ceb818..1cbd56241 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/clipboard/clipwindow.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/clipboard/clipwindow.py @@ -65,10 +65,9 @@ def __init__(self, parent): previousItems = QListWidget(centralWidget) //! [0] - connect(clipboard, SIGNAL("dataChanged()"), self, SLOT("updateClipboard()")) + clipboard.dataChanged.connect(self.updateClipboard) //! [0] - connect(mimeTypeCombo, SIGNAL("activated(const QString &)"), - self, SLOT("updateData(const QString &))") + mimeTypeCombo.activated[str].connect(self.updateData) currentLayout = QVBoxLayout(currentItem) currentLayout.addWidget(mimeTypeLabel) diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_kernel_qobject.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_kernel_qobject.py index 1de4dbbe8..7e50f6701 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_kernel_qobject.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_kernel_qobject.py @@ -1,52 +1,52 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of Qt for Python. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the documentation of Qt for Python. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ //! [0] lineEdit = qt_find_obj_child(myWidget, "QLineEdit", "my line edit") @@ -96,8 +96,8 @@ layout.inherits("QLayoutItem") # returns false //! [5] -print "MyClass::setPrecision(): (%s) invalid precision %f" % \ - (qPrintable(objectName()), newPrecision) +print("MyClass.setPrecision(): ({}) invalid precision {}".format(qPrintable(objectName()), + newPrecision)) //! [5] @@ -112,7 +112,7 @@ class MainWindow(QMainWindow): if obj == textEdit: if event.type() == QEvent.KeyPress: keyEvent = event - print "Ate key press", keyEvent.key() + print("Ate key press", keyEvent.key()) return true else: return false @@ -138,14 +138,14 @@ class MyObject(QObject): def timerEvent(self, event): - print "Timer ID:", event.timerId() + print("Timer ID:", event.timerId()) //! [8] //! [9] -list = window().queryList("QAbstractButton") -for obj in list: +a_list = window().queryList("QAbstractButton") +for obj in a_list: obj.setEnabled(false) //! [9] @@ -156,7 +156,7 @@ button = parentWidget.findChild(QPushButton, "button1") //! [11] -list = parentWidget.findChild(QListWidget) +a_list = parentWidget.findChild(QListWidget) //! [11] @@ -179,7 +179,7 @@ monitoredObj.installEventFilter(filterObj) class KeyPressEater(QObject): def eventFilter(self, obj, event): if event.type() == QEvent.KeyPress: - print "Ate key press", event.key() + print("Ate key press", event.key()) return True else: # standard event processing @@ -234,15 +234,16 @@ if receivers(SIGNAL('valueChanged()')) > 0: //! [22] label = QLabel() scrollBar = QScrollBar() -QObject.connect(scrollBar, SIGNAL('valueChanged()'), - label, SLOT('setNum()')) +QObject.connect(scrollBar, SIGNAL('valueChanged(int)'), + label, SLOT('setNum(int)')); +# or scrollBar.valueChanged.connect(label.setNum) //! [22] //! [23] // WRONG -QObject.connect(scrollBar, SIGNAL('valueChanged()'), - label, SLOT('setNum()')); +QObject.connect(scrollBar, SIGNAL('valueChanged(int value)'), + label, SLOT('setNum(int value)')); //! [23] @@ -250,8 +251,7 @@ QObject.connect(scrollBar, SIGNAL('valueChanged()'), class MyWidget(QWidget): def __init__(self): myButton = QPushButton(self) - connect(myButton, SIGNAL('clicked()'), - self, SIGNAL('buttonClicked()')) + myButton.clicked.connect(self.buttonClicked) //! [24] @@ -323,7 +323,7 @@ Q_PROPERTY(type name [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] - [USER bool]) + [USER bool]) //! [36] @@ -333,34 +333,40 @@ Q_PROPERTY(QString title READ title WRITE setTitle USER true) //! [38] -#this not apply for Python +#this does not apply to Python class MyClass(QObject): - Q_OBJECT - Q_ENUMS(Priority) + #Q_OBJECT, not needed + #Q_ENUMS(Priority), not supported -public: - MyClass(QObject *parent = 0); - ~MyClass(); + def __init__(self, parent=None): + pass - enum Priority { High, Low, VeryHigh, VeryLow }; - void setPriority(Priority priority); - Priority priority() const; + class Priority(Enum): + High = 1 + Low = 2 + VeryHigh = 3 + VeryLow 4 + + def setPriority(self, priority): + pass + + priority = Property(...) }; //! [38] //! [39] -#this not apply for Python +#this does not apply to Python Q_FLAGS(Options Alignment) //! [39] //! [40] -//: This name refers to a host name. +# This name refers to a host name. hostNameLabel.setText(self.tr("Name:")) -#: This text refers to a C++ code example. +# This text refers to a C++ code example. example = self.tr("Example") //! [40] diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.py b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.py new file mode 100644 index 000000000..6cf5dd21c --- /dev/null +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.py @@ -0,0 +1,74 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the documentation of Qt for Python. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +//! [0] + formWindow = QDesignerFormWindowInterface() + formWindow = QDesignerFormWindowInterface.findFormWindow(myWidget) +//! [0] + + +//! [1] + forms = [] # QList<QDesignerFormWindowInterface> + formWindow = QDesignerFormWindowInterface() + + manager = formEditor.formWindowManager() + + for i in range(manager.formWindowCount()): + formWindow = manager.formWindow(i) + forms.append(formWindow) +//! [1] + + +//! [2] + if formWindow.isManaged(myWidget): + formWindow.manageWidget(myWidget.childWidget) +//! [2] + + diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.cpp deleted file mode 100644 index 255231512..000000000 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of Qt for Python. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//! [0] - QDesignerPropertyEditorInterface *propertyEditor = 0; - propertyEditor = formEditor->propertyEditor(); - - connect(propertyEditor, SIGNAL(propertyChanged(QString, QVariant)), - this, SLOT(checkProperty(QString, QVariant))); -//! [0] - - -//! [1] - void checkProperty(QString property, QVariant value) { - QDesignerPropertyEditorInterface *propertyEditor = 0; - propertyEditor = formEditor->propertyEditor(); - - QObject *object = propertyeditor->object(); - MyCustomWidget *widget = qobject_cast<MyCustomWidget>(object); - - if (widget && property == aProperty && value != expectedValue) - {...} - } -//! [1] - - diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.py b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.py new file mode 100644 index 000000000..1e2ac506f --- /dev/null +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.py @@ -0,0 +1,71 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the documentation of Qt for Python. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +//! [0] + propertyEdit = QDesignerPropertyEditorInterface() + propertyEditor = formEditor.propertyEditor() + + propertyEditor.propertyChanged.connect(self.checkProperty) +//! [0] + + +//! [1] + def checkProperty(self, property, value): + propertyEditor = QDesignerPropertyEditorInterface() + propertyEditor = formEditor.propertyEditor() + + object = propertyeditor.object() + widget = MyCustomWidget(object) + + if (widget and property == aProperty and value != expectedValue): + # ... +//! [1] + + diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/dialogs/dialogs.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/dialogs/dialogs.py index 047434f6d..7bdcb0c91 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/dialogs/dialogs.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/dialogs/dialogs.py @@ -50,12 +50,10 @@ //! [0] -def find(self) - - if !self.findDialog: +def find(self): + if not self.findDialog: self.findDialog = FindDialog(self) - connect(findDialog, SIGNAL("findNext()"), self, SLOT("findNext()")) - + self.findDialog.findNext.connect(self.findNext) self.findDialog.show() self.findDialog.raise() @@ -72,58 +70,54 @@ def countWords(self): //! [1] //! [2] - mb = QMessageBox("Application Name", - "Hardware failure.\n\nDisk error detected\nDo you want to stop?", - QMessageBox.Question, - QMessageBox.Yes | QMessageBox.Default, - QMessageBox.No | QMessageBox.Escape, - QMessageBox.NoButton) - if mb.exec() == QMessageBox.No: - # try again + mb = QMessageBox("Application Name", + "Hardware failure.\n\nDisk error detected\nDo you want to stop?", + QMessageBox.Question, + QMessageBox.Yes | QMessageBox.Default, + QMessageBox.No | QMessageBox.Escape, + QMessageBox.NoButton) + if mb.exec() == QMessageBox.No: + # try again //! [2] //! [3] progress = QProgressDialog("Copying files...", "Abort Copy", 0, numFiles, self) progress.setWindowModality(Qt.WindowModal) - for i in rang(numFiles): + for i in range(numFiles): progress.setValue(i) if progress.wasCanceled(): break #... copy one file - + progress.setValue(numFiles) //! [3] //! [4] # Operation constructor -def __init__(self, parent): +def __init__(self, parent=None): QObject.__init__(self, parent) pd = QProgressDialog("Operation in progress.", "Cancel", 0, 100) - connect(pd, SIGNAL("canceled()"), self, SLOT("cancel()")) + pd.canceled.connect(self.cancel) t = QTimer(self) - connect(t, SIGNAL("timeout()"), self, SLOT("perform()")) + t.timeout.connect(self.perform) t.start(0) //! [4] //! [5] def perform(self): - pd.setValue(steps) #... perform one percent of the operation - steps++ + steps += 1 if steps > pd.maximum(): t.stop() //! [5] //! [6] def cancel(self): - t.stop() #... cleanup //! [6] - - diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.h b/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.h deleted file mode 100644 index 8607b6953..000000000 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of Qt for Python. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef WINDOW_H -#define WINDOW_H - -#include <QString> -#include <QStringList> -#include <QWidget> - -class QComboBox; -class QFrame; -class QTextBrowser; - -class Window : public QWidget -{ - Q_OBJECT - -public: - Window(QWidget *parent = 0); - -protected: - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - -private: - QComboBox *mimeTypeCombo; - QFrame *dropFrame; - QTextBrowser *textBrowser; - QString oldText; - QStringList oldMimeTypes; -}; - -#endif diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.py b/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.py new file mode 100644 index 000000000..66a6a7ba2 --- /dev/null +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/dropevents/window.py @@ -0,0 +1,65 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the examples of Qt for Python. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +from PySide2.QtWidgets import QWidget, QComboBox, QFrame, QTextBrowser + +class Window(QWidget): + + def __init__(self, parent=None): + self.mimeTypeCombo = QComboBox() + self.dropFrame = QFrame() + self.textBrowser = QTextBrowser() + self.oldText = "" + self.oldMimeTypes = [] + + def dragEnterEvent(self, event): + pass + def dropEvent(self, event): + pass diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedlayout/main.py b/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedlayout/main.py new file mode 100644 index 000000000..184128406 --- /dev/null +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedlayout/main.py @@ -0,0 +1,87 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the documentation of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +from PySide2.QtWidgets import QApplication, QWidget, QStackedLayout, QComboBox + +class Widget(QWidget) + def __init__(self, parent=None): + QWidget.__init__(self, parent) +//! [0] + self.firstPageWidget = QWidget() + self.secondPageWidget = QWidget() + self.thirdPageWidget = QWidget() + + self.stackedLayout = QStackedLayout() + self.stackedLayout.addWidget(self.firstPageWidget) + self.stackedLayout.addWidget(self.secondPageWidget) + self.stackedLayout.addWidget(self.thirdPageWidget) + +//! [0] //! [1] + self.pageComboBox = QComboBox() + self.pageComboBox.addItem(tr("Page 1")) + self.pageComboBox.addItem(tr("Page 2")) + self.pageComboBox.addItem(tr("Page 3")) + self.pageComboBox.activated.connect(self.stackedLayout.setCurrentIndex) +//! [1] + +//! [2] + self.mainLayout = QVBoxLayout() +//! [2] + self.mainLayout.addWidget(self.pageComboBox) +//! [3] + self.mainLayout.addLayout(self.stackedLayout) + self.setLayout(self.mainLayout) +//! [3] + +if __name__ == "__main__": + app = QApplication(sys.argv) + widget = Widget() + widget.show() + sys.exit(app.exec_()) diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedwidget/main.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedwidget/main.py index 98a08be98..6f2c49d8e 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedwidget/main.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedwidget/main.py @@ -64,8 +64,7 @@ pageComboBox.addItem(tr("Page 1")) pageComboBox.addItem(tr("Page 2")) pageComboBox.addItem(tr("Page 3")) - connect(pageComboBox, SIGNAL("activated(int)"), - stackedWidget, SLOT("setCurrentIndex(int)")) + pageComboBox.activated[int].connect(stackedWidget.setCurrentIndex) //! [1] //! [2] layout = QVBoxLayout() diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/qxmlquery/bindingExample.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/qxmlquery/bindingExample.py index 734f603a9..16c12b7bc 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/qxmlquery/bindingExample.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/qxmlquery/bindingExample.py @@ -49,11 +49,11 @@ ****************************************************************************/ //! [0] - QBuffer device; - device.setData(myQString.toUtf8()); - device.open(QIODevice::ReadOnly); + device = QBuffer() + device.setData(myQString.toUtf8()) + device.open(QIODevice.ReadOnly) - QXmlQuery query; - query.setQuery("doc($inputDocument)/query[theDocument]"); - query.bindVariable("inputDocument", &device); + query = QXmlQuery() + query.setQuery("doc($inputDocument)/query[theDocument]") + query.bindVariable("inputDocument", device) //! [0] diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/sqldatabase/sqldatabase.cpp b/sources/pyside2/doc/codesnippets/doc/src/snippets/sqldatabase/sqldatabase.py index 29ac9c87d..7c28cf5e6 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/sqldatabase/sqldatabase.cpp +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/sqldatabase/sqldatabase.py @@ -77,7 +77,7 @@ def QSqlField_snippets(): //! [3] field = QSqlField("age", QVariant.Int) - field.setValue(QString("123")) # casts QString to int + field.setValue(str(123)) # casts str to int //! [3] //! [4] @@ -247,7 +247,7 @@ def QSqlTableModel_snippets(): //! [25] model = QSqlTableModel() model.setTable("employee") - QString name = model.record(4).value("name") + name = model.record(4).value("name") //! [25] def sql_intro_snippets(): @@ -351,7 +351,7 @@ def sql_intro_snippets(): employeeId = query.value(0) query.exec_("INSERT INTO project (id, name, ownerid) " "VALUES (201, 'Manhattan Project', " - + QString.number(employeeId) + ')') + + str(employeeId) + ')') QSqlDatabase.database().commit() //! [39] diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/widgets-tutorial/template.py b/sources/pyside2/doc/codesnippets/doc/src/snippets/widgets-tutorial/template.py new file mode 100644 index 000000000..d38829fc7 --- /dev/null +++ b/sources/pyside2/doc/codesnippets/doc/src/snippets/widgets-tutorial/template.py @@ -0,0 +1,66 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the documentation of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +//! [main.cpp body] +import sys +from PySide2.QtWidgets import QApplication + +# Include header files for application components. +# ... + +if __name__ == "__main__": + app = QApplication(sys.argv) + + # Set up and show widgets. + # ... + + sys.exit(app.exec_()) +} +//! [main.cpp body] diff --git a/sources/pyside2/doc/codesnippets/examples/dialogs/classwizard/classwizard.cpp b/sources/pyside2/doc/codesnippets/examples/dialogs/classwizard/classwizard.py index 897410ed7..08032cf2a 100644 --- a/sources/pyside2/doc/codesnippets/examples/dialogs/classwizard/classwizard.cpp +++ b/sources/pyside2/doc/codesnippets/examples/dialogs/classwizard/classwizard.py @@ -142,8 +142,7 @@ class ClassInfoPage(QWizardPage): defaultCtorRadioButton.setChecked(True) - self.connect(defaultCtorRadioButton, SIGNAL("toggled(bool)"), - copyCtorCheckBox, SLOT("setEnabled(bool)")) + defaultCtorRadioButton.toggled[bool].connect(copyCtorCheckBox.setEnabled) //! [11] //! [12] registerField("className*", classNameLineEdit) @@ -201,14 +200,10 @@ class CodeStylePage(QWizardPage): baseIncludeLineEdit = QLineEdit() baseIncludeLabel.setBuddy(baseIncludeLineEdit) - self.connect(protectCheckBox, SIGNAL("toggled(bool)"), - macroNameLabel, SLOT("setEnabled(bool)")) - self.connect(protectCheckBox, SIGNAL("toggled(bool)"), - macroNameLineEdit, SLOT("setEnabled(bool)")) - self.connect(includeBaseCheckBox, SIGNAL("toggled(bool)"), - baseIncludeLabel, SLOT("setEnabled(bool)")) - self.connect(includeBaseCheckBox, SIGNAL(toggled(bool)), - baseIncludeLineEdit, SLOT("setEnabled(bool)")) + protectCheckBox.toggled[bool].connect(macroNameLabel.setEnabled) + protectCheckBox.toggled[bool].connect(macroNameLineEdit.setEnabled) + includeBaseCheckBox.toggled[bool].connect(baseIncludeLabel.setEnabled) + includeBaseCheckBox.toggled[bool].connect(baseIncludeLineEdit.setEnabled) self.registerField("comment", commentCheckBox) self.registerField("protect", protectCheckBox) diff --git a/sources/pyside2/doc/codesnippets/examples/dialogs/extension/finddialog.cpp b/sources/pyside2/doc/codesnippets/examples/dialogs/extension/finddialog.py index a8496f4c8..1872e631b 100644 --- a/sources/pyside2/doc/codesnippets/examples/dialogs/extension/finddialog.cpp +++ b/sources/pyside2/doc/codesnippets/examples/dialogs/extension/finddialog.py @@ -85,7 +85,7 @@ def __init__(self, parent): //! [2] //! [3] - connect(moreButton, SIGNAL("toggled(bool)"), extension, SLOT("setVisible(bool)")) + moreButton.toggled[bool].connect(extension.setVisible) extensionLayout = QVBoxLayout() extensionLayout.setMargin(0) diff --git a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.h index f9d97e6ce..bdb7bcf22 100644 --- a/sources/pyside2/doc/codesnippets/doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.cpp +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.h @@ -3,7 +3,7 @@ ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the documentation of Qt for Python. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage @@ -48,28 +48,65 @@ ** ****************************************************************************/ +from PySide2.QtWidgets import (QAction, QApplication, QMainWindow, QMenu, + QPlainTextEdit, QSessionManager) + + //! [0] - QDesignerFormWindowInterface *formWindow; - formWindow = QDesignerFormWindowInterface::findFormWindow(myWidget); -//! [0] +class MainWindow(QMainWindow): + def __init__(self, parent=None): + self.textEdit = QPlainTextEdit() + self.curFile = "" + # ... + + def loadFile(self, fileName): + pass + + def closeEvent(self, event): + pass + + def newFile(self): + pass + def open(self): + pass -//! [1] - QList<QDesignerFormWindowInterface *> forms; - QDesignerFormWindowInterface *formWindow; + def save(self): + pass - QDesignerFormWindowManagerInterface *manager = formEditor->formWindowManager(); + def saveAs(self): + pass - for (int i = 0; i < manager->formWindowCount(); i++) { - formWindow = manager->formWindow(i); - forms.append(formWindow); - } -//! [1] + def about(self): + pass + def documentWasModified(self): + pass + # Enable this only if QT_NO_SESSIONMANAGER is not defined + # def commitData(self): + # pass -//! [2] - if (formWindow->isManaged(myWidget)) - formWindow->manageWidget(myWidget->childWidget); -//! [2] + def createActions(self): + pass + def createStatusBar(self): + pass + def readSettings(self): + pass + + def writeSettings(self): + pass + + def maybeSave(self): + pass + + def saveFile(self, fileName): + pass + + def setCurrentFile(self, fileName): + pass + + def strippedName(self, fullFileName): + pass +//! [0] diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.py index b0331aa79..f976bb8e3 100644 --- a/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.cpp +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.py @@ -49,28 +49,30 @@ ############################################################################ //! [0] -from PySide2.QtGui import * +from PySide2.QtCore import Qt, QFile, QFileInfo, QSettings, QTextStream +from PySide2.QtGui import QIcon +from PySide2.Widgets import (QAction, QApplication, QFileDialog, QMainWindow, + QPlainTextEdit, QFileDialog, QMessageBox, ) //! [0] //! [1] -def __init__(self): +def __init__(self, parent=None): QMainWindow.__init__(self) //! [1] //! [2] - textEdit = QPlainTextEdit() - setCentralWidget(textEdit) + self.textEdit = QPlainTextEdit() + self.setCentralWidget(textEdit) - createActions() - createMenus() - createToolBars() - createStatusBar() + self.createActions() + self.createMenus() + self.createToolBars() + self.createStatusBar() - readSettings() + self.readSettings() - connect(textEdit.document(), SIGNAL("contentsChanged()"), - self, SLOT("documentWasModified()")) + self.textEdit.document().contentsChanged.connect(self.documentWasModified) - setCurrentFile("") - setUnifiedTitleAndToolBarOnMac(True) + self.setCurrentFile("") + self.setUnifiedTitleAndToolBarOnMac(True) //! [2] @@ -97,7 +99,7 @@ def open(self): //! [7] //! [8] if maybeSave(): fileName = QFileDialog.getOpenFileName(self) - if !fileName.isEmpty(): + if not fileName.isEmpty(): loadFile(fileName) //! [8] @@ -142,70 +144,68 @@ def MainWindow.createActions(self): Act = QAction(QIcon(":/images/new.png"), tr("&New"), self) Act.setShortcuts(QKeySequence.New) Act.setStatusTip(tr("Create a new file")) - connect(Act, SIGNAL("triggered()"), self, SLOT("newFile()")) + Act.triggered.connect(newFile) //! [19] - openAct = QAction(QIcon(":/images/open.png"), tr("&Open..."), self) + openAct = QAction(QIcon(":/images/open.png"), tr("&Open..."), self) openAct.setShortcuts(QKeySequence.Open) openAct.setStatusTip(tr("Open an existing file")) - connect(openAct, SIGNAL("triggered()"), self, SLOT("open()")) + openAct.triggered.connect(open) //! [18] //! [19] - saveAct = QAction(QIcon(":/images/save.png"), tr("&Save"), self) + saveAct = QAction(QIcon(":/images/save.png"), tr("&Save"), self) saveAct.setShortcuts(QKeySequence.Save) saveAct.setStatusTip(tr("Save the document to disk")) - connect(saveAct, SIGNAL("triggered()"), self, SLOT("save()")) + saveAct.triggered.connect(save) - saveAsAct = QAction(tr("Save &As..."), self) + saveAsAct = QAction(tr("Save &As..."), self) saveAsAct.setShortcuts(QKeySequence.SaveAs) saveAsAct.setStatusTip(tr("Save the document under a name")) - connect(saveAsAct, SIGNAL("triggered()"), self, SLOT("saveAs()")) + saveAsAct.triggered.connect(saveAs) //! [20] - exitAct = QAction(tr("E&xit"), self) + exitAct = QAction(tr("E&xit"), self) exitAct.setShortcut(tr("Ctrl+Q")) //! [20] exitAct.setStatusTip(tr("Exit the application")) - connect(exitAct, SIGNAL("triggered()"), self, SLOT("close()")) + exitAct.triggered.connect(close) //! [21] - cutAct = QAction(QIcon(":/images/cut.png"), tr("Cu&t"), self) + cutAct = QAction(QIcon(":/images/cut.png"), tr("Cu&t"), self) //! [21] cutAct.setShortcuts(QKeySequence.Cut) cutAct.setStatusTip(tr("Cut the current selection's contents to the " "clipboard")) - connect(cutAct, SIGNAL("triggered()"), textEdit, SLOT("cut()")) + cutAct.triggered.connect(cut) - copyAct = QAction(QIcon(":/images/copy.png"), tr("&Copy"), self) + copyAct = QAction(QIcon(":/images/copy.png"), tr("&Copy"), self) copyAct.setShortcuts(QKeySequence.Copy) copyAct.setStatusTip(tr("Copy the current selection's contents to the " "clipboard")) - connect(copyAct, SIGNAL("triggered()"), textEdit, SLOT("copy()")) + copyAct.triggered.connect(copy) - pasteAct = QAction(QIcon(":/images/paste.png"), tr("&Paste"), self) + pasteAct = QAction(QIcon(":/images/paste.png"), tr("&Paste"), self) pasteAct.setShortcuts(QKeySequence.Paste) pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " "selection")) - connect(pasteAct, SIGNAL("triggered()"), textEdit, SLOT("paste()")) + pasteAct.triggered.connect(textEdit.paste) - aboutAct = QAction(tr("&About"), self) + aboutAct = QAction(tr("&About"), self) aboutAct.setStatusTip(tr("Show the application's About box")) - connect(aboutAct, SIGNAL("triggered()"), self, SLOT("about()")) + aboutAct.triggered.connect(about) //! [22] aboutQtAct = QAction(tr("About &Qt"), self) aboutQtAct.setStatusTip(tr("Show the Qt library's About box")) - connect(aboutQtAct, SIGNAL("triggered()"), qApp, SLOT("aboutQt()")) + aboutQtAct.triggered.connect(qApp.aboutQt) //! [22] //! [23] cutAct.setEnabled(False) //! [23] //! [24] copyAct.setEnabled(False) - connect(textEdit, SIGNAL("copyAvailable(bool)"), - cutAct, SLOT("setEnabled(bool)")) - connect(textEdit, SIGNAL("copyAvailable(bool)"), - copyAct, SLOT("setEnabled(bool)")) + textEdit.copyAvailable[bool].connect(cutAct.setEnabled) + textEdit.copyAvailable[bool].connect(copyAct.setEnabled) } //! [24] @@ -298,10 +298,8 @@ def loadFile(self, fileName): //! [42] //! [43] file = QFile(fileName) if !file.open(QFile.ReadOnly | QFile.Text): - QMessageBox.warning(self, tr("Application"), - tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())) + QMessageBox.warning(self, tr("Application"), tr("Cannot read file " + "{}:\n{}.".format(fileName, file.errorString()))) return in = QTextStream(file) @@ -309,8 +307,8 @@ def loadFile(self, fileName): textEdit.setPlainText(in.readAll()) QApplication.restoreOverrideCursor() - setCurrentFile(fileName) - statusBar().showMessage(tr("File loaded"), 2000) + self.setCurrentFile(fileName) + self.statusBar().showMessage(tr("File loaded"), 2000) //! [43] diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/dockwidgets/mainwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/dockwidgets/mainwindow.py index e1a9f556e..55d551c24 100644 --- a/sources/pyside2/doc/codesnippets/examples/mainwindows/dockwidgets/mainwindow.cpp +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/dockwidgets/mainwindow.py @@ -142,7 +142,7 @@ def save(self): .arg(fileName) .arg(file.errorString())) return - + out = QTextStream(file) QApplication.setOverrideCursor(Qt::WaitCursor) @@ -177,7 +177,7 @@ def insertCustomer(self, customer): for i in range(customerList.size()): cursor.insertBlock() cursor.insertText(customerList.at(i)) - + cursor.endEditBlock() else: oldcursor.endEditBlock() @@ -248,8 +248,6 @@ def createDockWindows(self): addDockWidget(Qt.RightDockWidgetArea, dock) viewMenu.addAction(dock.toggleViewAction()) - connect(customerList, SIGNAL("currentTextChanged(const QString &)"), - self, SLOT("insertCustomer(const QString &)")) - connect(paragraphsList, SIGNAL("currentTextChanged(const QString &)"), - self, SLOT("addParagraph(const QString &)")) + customerList.currentTextChanged[str].connect(self.insertCostumer) + paragraphsList.currentTextChanged[str].connect(self.addParagraph) //! [9] diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/mainwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/mainwindow.py index 6ed5f5466..b0bbed810 100644 --- a/sources/pyside2/doc/codesnippets/examples/mainwindows/mainwindow.cpp +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/mainwindow.py @@ -196,63 +196,63 @@ def createActions(self): Act = new QAction(tr("&New"), self) Act.setShortcuts(QKeySequence.New) Act.setStatusTip(tr("Create a new file")) - connect(Act, SIGNAL("triggered()"), self, SLOT("newFile()")) + Act.triggered.connect(newFile) //! [4] openAct = QAction(tr("&Open..."), self) openAct.setShortcuts(QKeySequence.Open) openAct.setStatusTip(tr("Open an existing file")) - connect(openAct, SIGNAL("triggered()"), self, SLOT("open()")) + openAct.triggered.connect(open) //! [5] saveAct = QAction(tr("&Save"), self) saveAct.setShortcuts(QKeySequence.Save) saveAct.setStatusTip(tr("Save the document to disk")) - connect(saveAct, SIGNAL("triggered()"), self, SLOT("save()")) + saveAct.triggered.connect(save) printAct = QAction(tr("&Print..."), self) printAct.setShortcuts(QKeySequence.Print) printAct.setStatusTip(tr("Print the document")) - connect(printAct, SIGNAL("triggered()"), self, SLOT("print_()")) + printAct.triggered.connect(print_) exitAct = QAction(tr("E&xit"), self) exitAct.setShortcut(tr("Ctrl+Q")) exitAct.setStatusTip(tr("Exit the application")) - connect(exitAct, SIGNAL("triggered()"), self, SLOT("close()")) + exitAct.triggered.connect(close) undoAct = QAction(tr("&Undo"), self) undoAct.setShortcuts(QKeySequence.Undo) undoAct.setStatusTip(tr("Undo the last operation")) - connect(undoAct, SIGNAL("triggered()"), self, SLOT("undo()")) + undoAct.triggered.connect(undo) redoAct = QAction(tr("&Redo"), self) redoAct.setShortcuts(QKeySequence.Redo) redoAct.setStatusTip(tr("Redo the last operation")) - connect(redoAct, SIGNAL("triggered()"), self, SLOT("redo()")) + redoAct.triggered.connect(redo) cutAct = QAction(tr("Cu&t"), self) cutAct.setShortcuts(QKeySequence.Cut) cutAct.setStatusTip(tr("Cut the current selection's contents to the " "clipboard")) - connect(cutAct, SIGNAL("triggered()"), self, SLOT("cut()")) + cutAct.triggered.connect(cut) copyAct = QAction(tr("&Copy"), self) copyAct.setShortcut(tr("Ctrl+C")) copyAct.setStatusTip(tr("Copy the current selection's contents to the " "clipboard")) - connect(copyAct, SIGNAL("triggered()"), self, SLOT("copy()")) + copyAct.triggered.connect(copy) pasteAct = QAction(tr("&Paste"), self) pasteAct.setShortcuts(QKeySequence.Paste) pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " "selection")) - connect(pasteAct, SIGNAL("triggered()"), self, SLOT("paste()")) + pasteAct.triggered.connect(paste) boldAct = QAction(tr("&Bold"), self) boldAct.setCheckable(True) boldAct.setShortcut(tr("Ctrl+B")) boldAct.setStatusTip(tr("Make the text bold")) - connect(boldAct, SIGNAL("triggered()"), self, SLOT("bold()")) + boldAct.triggered.connect(bold) QFont boldFont = boldAct.font() boldFont.setBold(True) @@ -262,7 +262,7 @@ def createActions(self): italicAct.setCheckable(True) italicAct.setShortcut(tr("Ctrl+I")) italicAct.setStatusTip(tr("Make the text italic")) - connect(italicAct, SIGNAL("triggered()"), self, SLOT("italic()")) + italicAct.triggered.connect(italic) QFont italicFont = italicAct.font() italicFont.setItalic(True) @@ -271,45 +271,44 @@ def createActions(self): setLineSpacingAct = QAction(tr("Set &Line Spacing..."), self) setLineSpacingAct.setStatusTip(tr("Change the gap between the lines of a " "paragraph")) - connect(setLineSpacingAct, SIGNAL("triggered()"), self, SLOT("setLineSpacing()")) + setLineSpacingAct.triggered.connect(setLineSpacing) setParagraphSpacingAct = QAction(tr("Set &Paragraph Spacing..."), self) setLineSpacingAct.setStatusTip(tr("Change the gap between paragraphs")) - connect(setParagraphSpacingAct, SIGNAL("triggered()"), - self, SLOT("setParagraphSpacing()")) + setParagraphSpacingAct.triggered.connect(setParagraphSpacing) aboutAct = QAction(tr("&About"), self) aboutAct.setStatusTip(tr("Show the application's About box")) - connect(aboutAct, SIGNAL("triggered()"), self, SLOT("about()")) + aboutAct.triggered.connect(about) aboutQtAct = QAction(tr("About &Qt"), self) aboutQtAct.setStatusTip(tr("Show the Qt library's About box")) - connect(aboutQtAct, SIGNAL("triggered()"), qApp, SLOT("aboutQt()")) - connect(aboutQtAct, SIGNAL("triggered()"), self, SLOT("aboutQt()")) + aboutQtAct.triggered.connect(qApp.aboutQt) + aboutQtAct.triggered.connect(aboutQt) leftAlignAct = QAction(tr("&Left Align"), self) leftAlignAct.setCheckable(True) leftAlignAct.setShortcut(tr("Ctrl+L")) leftAlignAct.setStatusTip(tr("Left align the selected text")) - connect(leftAlignAct, SIGNAL("triggered()"), self, SLOT("leftAlign()")) + leftAlignAct.triggered.connect(leftAlign) rightAlignAct = QAction(tr("&Right Align"), self) rightAlignAct.setCheckable(True) rightAlignAct.setShortcut(tr("Ctrl+R")) rightAlignAct.setStatusTip(tr("Right align the selected text")) - connect(rightAlignAct, SIGNAL("triggered()"), self, SLOT("rightAlign()")) + rightAlignAct.triggered.connect.(rightAlign) justifyAct = QAction(tr("&Justify"), self) justifyAct.setCheckable(True) justifyAct.setShortcut(tr("Ctrl+J")) justifyAct.setStatusTip(tr("Justify the selected text")) - connect(justifyAct, SIGNAL("triggered()"), self, SLOT("justify()")) + justifyAct.triggered.connect(justify) centerAct = QAction(tr("&Center"), self) centerAct.setCheckable(True) centerAct.setShortcut(tr("Ctrl+E")) centerAct.setStatusTip(tr("Center the selected text")) - connect(centerAct, SIGNAL("triggered()"), self, SLOT("center()")) + centerAct.triggered.connect(center) //! [6] //! [7] alignmentGroup = QActionGroup(self) diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.cpp deleted file mode 100644 index cfee5cdca..000000000 --- a/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.cpp +++ /dev/null @@ -1,381 +0,0 @@ -############################################################################ -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the examples of Qt for Python. -## -## $QT_BEGIN_LICENSE:BSD$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## BSD License Usage -## Alternatively, you may use this file under the terms of the BSD license -## as follows: -## -## "Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions are -## met: -## * Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## * Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in -## the documentation and/or other materials provided with the -## distribution. -## * Neither the name of The Qt Company Ltd nor the names of its -## contributors may be used to endorse or promote products derived -## from this software without specific prior written permission. -## -## -## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -## "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 COPYRIGHT -## OWNER OR CONTRIBUTORS 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." -## -## $QT_END_LICENSE$ -## -############################################################################ - -from PySide2.QtGui import * - -def __init__(self): - - mdiArea = QMdiArea() - mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) - mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) - setCentralWidget(mdiArea) - connect(mdiArea, SIGNAL("subWindowActivated(QMdiSubWindow *)"), - self, SLOT("updateMenus()")) - windowMapper = QSignalMapper(self) - connect(windowMapper, SIGNAL("mapped(QWidget *)"), - self, SLOT("setActiveSubWindow(QWidget *)")) - - createActions() - createMenus() - createToolBars() - createStatusBar() - updateMenus() - - readSettings() - - setWindowTitle(tr("MDI")) - setUnifiedTitleAndToolBarOnMac(True) - - -def closeEvent(self, event): - mdiArea.closeAllSubWindows() - if self.activeMdiChild(): - event.ignore() - else: - self.writeSettings() - event.accept() - -def File(self): - child = self.createMdiChild() - child.File() - child.show() - - -def open(self): - fileName = QFileDialog.getOpenFileName(self) - if !fileName.isEmpty()): - existing = self.findMdiChild(fileName) - if existing: - mdiArea.setActiveSubWindow(existing) - return - - child = createMdiChild() - if child.loadFile(fileName)): - statusBar().showMessage(tr("File loaded"), 2000) - child.show() - else: - child.close() - -def save(self): - if self.activeMdiChild() && self.activeMdiChild().save(): - self.statusBar().showMessage(tr("File saved"), 2000) - -def saveAs(self): - if self.activeMdiChild() && self.activeMdiChild().saveAs(): - self.statusBar().showMessage(tr("File saved"), 2000) - -def cut(self): - if self.activeMdiChild(): - self.activeMdiChild().cut() - -def copy(self): - if self.activeMdiChild(): - activeMdiChild().copy() - -def paste(self): - if self.activeMdiChild(): - activeMdiChild().paste() - -def about(self): - QMessageBox.about(self, tr("About MDI"), - tr("The <b>MDI</b> example demonstrates how to write multiple " - "document interface applications using Qt.")") - -def updateMenus(self): - hasMdiChild = (activeMdiChild() != 0) - self.saveAct.setEnabled(hasMdiChild) - self.saveAsAct.setEnabled(hasMdiChild) - self.pasteAct.setEnabled(hasMdiChild) - self.closeAct.setEnabled(hasMdiChild) - self.closeAllAct.setEnabled(hasMdiChild) - self.tileAct.setEnabled(hasMdiChild) - self.cascadeAct.setEnabled(hasMdiChild) - self.nextAct.setEnabled(hasMdiChild) - self.previousAct.setEnabled(hasMdiChild) - self.separatorAct.setVisible(hasMdiChild) - - hasSelection = (self.activeMdiChild() && - self.activeMdiChild().textCursor().hasSelection()") - self.cutAct.setEnabled(hasSelection) - self.copyAct.setEnabled(hasSelection) - -def updateWindowMenu(self): - self.windowMenu.clear() - self.windowMenu.addAction(closeAct) - self.windowMenu.addAction(closeAllAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(tileAct) - self.windowMenu.addAction(cascadeAct) - self.windowMenu.addSeparator() - self.windowMenu.addAction(nextAct) - self.windowMenu.addAction(previousAct) - self.windowMenu.addAction(separatorAct) - - windows = mdiArea.subWindowList() - separatorAct.setVisible(!windows.isEmpty()") - - for i in range((int i = 0 i < windows.size(); ++i) - MdiChild *child = qobject_cast<MdiChild *>(windows.at(i).widget()") - - QString text - if (i < 9) - text = tr("&%1 %2").arg(i + 1) - .arg(child.userFriendlyCurrentFile()") - else - text = tr("%1 %2").arg(i + 1) - .arg(child.userFriendlyCurrentFile()") - - QAction *action = windowMenu.addAction(text) - action.setCheckable(True) - action .setChecked(child == activeMdiChild()") - connect(action, SIGNAL("triggered()"), windowMapper, SLOT("map()")) - windowMapper.setMapping(action, windows.at(i)") - - - -MdiChild *createMdiChild() - - MdiChild *child = MdiChild - mdiArea.addSubWindow(child) - - connect(child, SIGNAL("copyAvailable(bool)"), - cutAct, SLOT("setEnabled(bool)")) - connect(child, SIGNAL("copyAvailable(bool)"), - copyAct, SLOT("setEnabled(bool)")) - - return child - - -def createActions() - - Act = new QAction(QIcon(":/images/new.png"), tr("&New"), self) - Act.setShortcuts(QKeySequence.New) - Act.setStatusTip(tr("Create a new file")") - connect(Act, SIGNAL("triggered()"), self, SLOT("newFile()")) - - openAct = QAction(QIcon(":/images/open.png"), tr("&Open..."), self) - openAct.setShortcuts(QKeySequence.Open) - openAct.setStatusTip(tr("Open an existing file")") - connect(openAct, SIGNAL("triggered()"), self, SLOT("open()")) - - saveAct = QAction(QIcon(":/images/save.png"), tr("&Save"), self) - saveAct.setShortcuts(QKeySequence.Save) - saveAct.setStatusTip(tr("Save the document to disk")") - connect(saveAct, SIGNAL("triggered()"), self, SLOT("save()")) - - saveAsAct = QAction(tr("Save &As..."), self) - saveAsAct.setShortcuts(QKeySequence.SaveAs) - saveAsAct.setStatusTip(tr("Save the document under a name")") - connect(saveAsAct, SIGNAL("triggered()"), self, SLOT("saveAs()")) - -//! [0] - exitAct = QAction(tr("E&xit"), self) - exitAct.setShortcut(tr("Ctrl+Q")") - exitAct.setStatusTip(tr("Exit the application")") - connect(exitAct, SIGNAL("triggered()"), qApp, SLOT("closeAllWindows()")) -//! [0] - - cutAct = QAction(QIcon(":/images/cut.png"), tr("Cu&t"), self) - cutAct.setShortcuts(QKeySequence.Cut) - cutAct.setStatusTip(tr("Cut the current selection's contents to the " - "clipboard")") - connect(cutAct, SIGNAL("triggered()"), self, SLOT("cut()")) - - copyAct = QAction(QIcon(":/images/copy.png"), tr("&Copy"), self) - copyAct.setShortcuts(QKeySequence.Copy) - copyAct.setStatusTip(tr("Copy the current selection's contents to the " - "clipboard")") - connect(copyAct, SIGNAL("triggered()"), self, SLOT("copy()")) - - pasteAct = QAction(QIcon(":/images/paste.png"), tr("&Paste"), self) - pasteAct.setShortcuts(QKeySequence.Paste) - pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " - "selection")") - connect(pasteAct, SIGNAL("triggered()"), self, SLOT("paste()")) - - closeAct = QAction(tr("Cl&ose"), self) - closeAct.setShortcut(tr("Ctrl+F4")") - closeAct.setStatusTip(tr("Close the active window")") - connect(closeAct, SIGNAL("triggered()"), - mdiArea, SLOT("closeActiveSubWindow()")) - - closeAllAct = QAction(tr("Close &All"), self) - closeAllAct.setStatusTip(tr("Close all the windows")") - connect(closeAllAct, SIGNAL("triggered()"), - mdiArea, SLOT("closeAllSubWindows()")) - - tileAct = QAction(tr("&Tile"), self) - tileAct.setStatusTip(tr("Tile the windows")") - connect(tileAct, SIGNAL("triggered()"), mdiArea, SLOT("tileSubWindows()")) - - cascadeAct = QAction(tr("&Cascade"), self) - cascadeAct.setStatusTip(tr("Cascade the windows")") - connect(cascadeAct, SIGNAL("triggered()"), mdiArea, SLOT("cascadeSubWindows()")) - - nextAct = QAction(tr("Ne&xt"), self) - nextAct.setShortcuts(QKeySequence.NextChild) - nextAct.setStatusTip(tr("Move the focus to the next window")") - connect(nextAct, SIGNAL("triggered()"), - mdiArea, SLOT("activateNextSubWindow()")) - - previousAct = QAction(tr("Pre&vious"), self) - previousAct.setShortcuts(QKeySequence.PreviousChild) - previousAct.setStatusTip(tr("Move the focus to the previous " - "window")") - connect(previousAct, SIGNAL("triggered()"), - mdiArea, SLOT("activatePreviousSubWindow()")) - - separatorAct = QAction(self) - separatorAct.setSeparator(True) - - aboutAct = QAction(tr("&About"), self) - aboutAct.setStatusTip(tr("Show the application's About box")") - connect(aboutAct, SIGNAL("triggered()"), self, SLOT("about()")) - - aboutQtAct = QAction(tr("About &Qt"), self) - aboutQtAct.setStatusTip(tr("Show the Qt library's About box")") - connect(aboutQtAct, SIGNAL("triggered()"), qApp, SLOT("aboutQt()")) - - -def createMenus() - - fileMenu = menuBar().addMenu(tr("&File")") - fileMenu.addAction(Act) - fileMenu.addAction(openAct) - fileMenu.addAction(saveAct) - fileMenu.addAction(saveAsAct) - fileMenu.addSeparator() - QAction *action = fileMenu.addAction(tr("Switch layout direction")") - connect(action, SIGNAL("triggered()"), self, SLOT("switchLayoutDirection()")) - fileMenu.addAction(exitAct) - - editMenu = menuBar().addMenu(tr("&Edit")") - editMenu.addAction(cutAct) - editMenu.addAction(copyAct) - editMenu.addAction(pasteAct) - - windowMenu = menuBar().addMenu(tr("&Window")") - updateWindowMenu() - connect(windowMenu, SIGNAL("aboutToShow()"), self, SLOT("updateWindowMenu()")) - - menuBar().addSeparator() - - helpMenu = menuBar().addMenu(tr("&Help")") - helpMenu.addAction(aboutAct) - helpMenu.addAction(aboutQtAct) - - -def createToolBars() - - fileToolBar = addToolBar(tr("File")") - fileToolBar.addAction(Act) - fileToolBar.addAction(openAct) - fileToolBar.addAction(saveAct) - - editToolBar = addToolBar(tr("Edit")") - editToolBar.addAction(cutAct) - editToolBar.addAction(copyAct) - editToolBar.addAction(pasteAct) - - -def createStatusBar() - - statusBar().showMessage(tr("Ready")") - - -def readSettings() - - QSettings settings("Trolltech", "MDI Example") - QPoint pos = settings.value("pos", QPoint(200, 200)").toPoint() - QSize size = settings.value("size", QSize(400, 400)").toSize() - move(pos) - resize(size) - - -def writeSettings() - - QSettings settings("Trolltech", "MDI Example") - settings.setValue("pos", pos()") - settings.setValue("size", size()") - - -MdiChild *activeMdiChild() - - if (QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow()") - return qobject_cast<MdiChild *>(activeSubWindow.widget()") - return 0 - - -QMdiSubWindow *findMdiChild(const QString &fileName) - - QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath() - - foreach (QMdiSubWindow *window, mdiArea.subWindowList()") - MdiChild *mdiChild = qobject_cast<MdiChild *>(window.widget()") - if (mdiChild.currentFile() == canonicalFilePath) - return window - - return 0 - - -def switchLayoutDirection() - - if (layoutDirection() == Qt.LeftToRight) - qApp.setLayoutDirection(Qt.RightToLeft) - else - qApp.setLayoutDirection(Qt.LeftToRight) - - -def setActiveSubWindow(QWidget *window) - - if (!window) - return - mdiArea.setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window)") - diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.py b/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.py new file mode 100644 index 000000000..41f515847 --- /dev/null +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.py @@ -0,0 +1,360 @@ +############################################################################ +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the examples of Qt for Python. +## +## $QT_BEGIN_LICENSE:BSD$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## BSD License Usage +## Alternatively, you may use this file under the terms of the BSD license +## as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "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 COPYRIGHT +## OWNER OR CONTRIBUTORS 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." +## +## $QT_END_LICENSE$ +## +############################################################################ + +from PySide2.QtGui import * + +class QMdiSubWindow(QMainWindow): + def __init__(self, parent=None): + QMainWindow.__init__(self, parent) + + mdiArea = QMdiArea() + mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) + mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) + setCentralWidget(mdiArea) + mdiArea.subWindowActivated[QMdiSubWindow].connect(updateMenus) + windowMapper = QSignalMapper(self) + windowMapper.mapped[QWidget].connect(setActiveSubWindow) + + self.createActions() + self.createMenus() + self.createToolBars() + self.createStatusBar() + self.updateMenus() + self.readSettings() + self.setWindowTitle(tr("MDI")) + self.setUnifiedTitleAndToolBarOnMac(True) + + + def closeEvent(self, event): + mdiArea.closeAllSubWindows() + if self.activeMdiChild(): + event.ignore() + else: + self.writeSettings() + event.accept() + + def File(self): + child = self.createMdiChild() + child.File() + child.show() + + + def open(self): + fileName = QFileDialog.getOpenFileName(self) + if not fileName.isEmpty(): + existing = self.findMdiChild(fileName) + if existing: + mdiArea.setActiveSubWindow(existing) + return + + child = createMdiChild() + if child.loadFile(fileName): + statusBar().showMessage(tr("File loaded"), 2000) + child.show() + else: + child.close() + + def save(self): + if self.activeMdiChild() and self.activeMdiChild().save(): + self.statusBar().showMessage(tr("File saved"), 2000) + + def saveAs(self): + if self.activeMdiChild() and self.activeMdiChild().saveAs(): + self.statusBar().showMessage(tr("File saved"), 2000) + + def cut(self): + if self.activeMdiChild(): + self.activeMdiChild().cut() + + def copy(self): + if self.activeMdiChild(): + activeMdiChild().copy() + + def paste(self): + if self.activeMdiChild(): + activeMdiChild().paste() + + def about(self): + QMessageBox.about(self, tr("About MDI"), + tr("The <b>MDI</b> example demonstrates how to write multiple " + "document interface applications using Qt.")) + + def updateMenus(self): + hasMdiChild = (activeMdiChild() != 0) + self.saveAct.setEnabled(hasMdiChild) + self.saveAsAct.setEnabled(hasMdiChild) + self.pasteAct.setEnabled(hasMdiChild) + self.closeAct.setEnabled(hasMdiChild) + self.closeAllAct.setEnabled(hasMdiChild) + self.tileAct.setEnabled(hasMdiChild) + self.cascadeAct.setEnabled(hasMdiChild) + self.nextAct.setEnabled(hasMdiChild) + self.previousAct.setEnabled(hasMdiChild) + self.separatorAct.setVisible(hasMdiChild) + + hasSelection = (self.activeMdiChild() and + self.activeMdiChild().textCursor().hasSelection()) + self.cutAct.setEnabled(hasSelection) + self.copyAct.setEnabled(hasSelection) + + def updateWindowMenu(self): + self.windowMenu.clear() + self.windowMenu.addAction(closeAct) + self.windowMenu.addAction(closeAllAct) + self.windowMenu.addSeparator() + self.windowMenu.addAction(tileAct) + self.windowMenu.addAction(cascadeAct) + self.windowMenu.addSeparator() + self.windowMenu.addAction(nextAct) + self.windowMenu.addAction(previousAct) + self.windowMenu.addAction(separatorAct) + + windows = mdiArea.subWindowList() + separatorAct.setVisible(not windows.isEmpty()) + + for i in range(0, windows.size()): + child = windows.at(i).widget() + + text = "" + if i < 9: + text = "{} {}".format(i + 1, child.userFriendlyCurrentFile()) + else: + text = "{} {}".format(i + 1, child.userFriendlyCurrentFile()) + + action = windowMenu.addAction(text) + action.setCheckable(True) + action.setChecked(child == activeMdiChild()) + action.triggered.connect(windowMapper.map) + windowMapper.setMapping(action, windows.at(i)) + + createMdiChild = MdiChild() + + child = MdiChild() + mdiArea.addSubWindow(child) + + child.copyAvailable[bool].connect(cutAct.setEnabled) + child.copyAvailable[bool].connect(copyAct.setEnabled) + + return child + + + def createActions(self): + + Act = QAction(QIcon(":/images/new.png"), tr("&New"), self) + Act.setShortcuts(QKeySequence.New) + Act.setStatusTip(tr("Create a new file")) + Act.triggered.connect(self.newFile) + + openAct = QAction(QIcon(":/images/open.png"), tr("&Open..."), self) + openAct.setShortcuts(QKeySequence.Open) + openAct.setStatusTip(tr("Open an existing file")) + openAct.triggered.connect(self.open) + + saveAct = QAction(QIcon(":/images/save.png"), tr("&Save"), self) + saveAct.setShortcuts(QKeySequence.Save) + saveAct.setStatusTip(tr("Save the document to disk")) + saveAct.triggered.connect(self.save) + + saveAsAct = QAction(tr("Save &As..."), self) + saveAsAct.setShortcuts(QKeySequence.SaveAs) + saveAsAct.setStatusTip(tr("Save the document under a name")) + saveAsAct.triggered.connect(self.saveAs) + +//! [0] + exitAct = QAction(tr("E&xit"), self) + exitAct.setShortcut(tr("Ctrl+Q")) + exitAct.setStatusTip(tr("Exit the application")) + exitAct.triggered.connect(qApp.closeAllWindows) +//! [0] + + cutAct = QAction(QIcon(":/images/cut.png"), tr("Cu&t"), self) + cutAct.setShortcuts(QKeySequence.Cut) + cutAct.setStatusTip(tr("Cut the current selection's contents to the " + "clipboard")) + cutAct.triggered.connect(self.cut) + + copyAct = QAction(QIcon(":/images/copy.png"), tr("&Copy"), self) + copyAct.setShortcuts(QKeySequence.Copy) + copyAct.setStatusTip(tr("Copy the current selection's contents to the " + "clipboard")) + copyAct.triggered.connect(self.copy) + + pasteAct = QAction(QIcon(":/images/paste.png"), tr("&Paste"), self) + pasteAct.setShortcuts(QKeySequence.Paste) + pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " + "selection")) + pasteAct.triggered.connect(self.paste) + + closeAct = QAction(tr("Cl&ose"), self) + closeAct.setShortcut(tr("Ctrl+F4")) + closeAct.setStatusTip(tr("Close the active window")) + closeAct.triggered.connect(mdiArea.closeActiveSubWindow) + + closeAllAct = QAction(tr("Close &All"), self) + closeAllAct.setStatusTip(tr("Close all the windows")) + closeAllAct.triggered.connect(mdiArea.closeAllSubWindows) + + tileAct = QAction(tr("&Tile"), self) + tileAct.setStatusTip(tr("Tile the windows")) + tileAct.triggered.connect(mdiArea.tileSubWindows) + + cascadeAct = QAction(tr("&Cascade"), self) + cascadeAct.setStatusTip(tr("Cascade the windows")) + cascadeAct.triggered.connect(mdiArea.cascadeSubWindows) + + nextAct = QAction(tr("Ne&xt"), self) + nextAct.setShortcuts(QKeySequence.NextChild) + nextAct.setStatusTip(tr("Move the focus to the next window")) + nextAct.triggered.connect(mdiArea.activateNextSubWindow) + + previousAct = QAction(tr("Pre&vious"), self) + previousAct.setShortcuts(QKeySequence.PreviousChild) + previousAct.setStatusTip(tr("Move the focus to the previous " + "window")) + previousAct.triggered.connect(mdiArea.activatePreviousSubWindow) + + separatorAct = QAction(self) + separatorAct.setSeparator(True) + + aboutAct = QAction(tr("&About"), self) + aboutAct.setStatusTip(tr("Show the application's About box")) + aboutAct.triggered.connect(self.about) + + aboutQtAct = QAction(tr("About &Qt"), self) + aboutQtAct.setStatusTip(tr("Show the Qt library's About box")) + aboutQtAct.triggered.connect(qApp.aboutQt) + + + def createMenus(self): + + fileMenu = menuBar().addMenu(tr("&File")) + fileMenu.addAction(Act) + fileMenu.addAction(openAct) + fileMenu.addAction(saveAct) + fileMenu.addAction(saveAsAct) + fileMenu.addSeparator() + action = fileMenu.addAction(tr("Switch layout direction")) + action.triggered.connect(self.switchLayoutDirection) + fileMenu.addAction(exitAct) + + editMenu = menuBar().addMenu(tr("&Edit")) + editMenu.addAction(cutAct) + editMenu.addAction(copyAct) + editMenu.addAction(pasteAct) + + windowMenu = menuBar().addMenu(tr("&Window")) + updateWindowMenu() + windowMenu.aboutToShow.connect(self.updateWindowMenu) + + menuBar().addSeparator() + + helpMenu = menuBar().addMenu(tr("&Help")) + helpMenu.addAction(aboutAct) + helpMenu.addAction(aboutQtAct) + + + def createToolBars(self): + fileToolBar = addToolBar(tr("File")) + fileToolBar.addAction(Act) + fileToolBar.addAction(openAct) + fileToolBar.addAction(saveAct) + + editToolBar = addToolBar(tr("Edit")) + editToolBar.addAction(cutAct) + editToolBar.addAction(copyAct) + editToolBar.addAction(pasteAct) + + + def createStatusBar(self): + statusBar().showMessage(tr("Ready")) + + + def readSettings(self): + settings = QSettings("Trolltech", "MDI Example") + QPoint pos = settings.value("pos", QPoint(200, 200)").toPoint() + QSize size = settings.value("size", QSize(400, 400)").toSize() + move(pos) + resize(size) + + def writeSettings(self): + QSettings settings("Trolltech", "MDI Example") + settings.setValue("pos", pos()") + settings.setValue("size", size()") + + + activeMdiChild = MdiChild() + activeSubWindow = mdiArea.activeSubWindow() + if activeSubWindow: + return activeSubWindow.widget() + return 0 + + + def findMdiChild(self, fileName): + + canonicalFilePath = QFileInfo(fileName).canonicalFilePath() + + for window in mdiArea.subWindowList(): + mdiChild = window.widget() + if mdiChild.currentFile() == canonicalFilePath: + return window + return 0 + + + def switchLayoutDirection(self) + if layoutDirection() == Qt.LeftToRight: + qApp.setLayoutDirection(Qt.RightToLeft) + else: + qApp.setLayoutDirection(Qt.LeftToRight) + + + def setActiveSubWindow(self, window): + if not window: + return + mdiArea.setActiveSubWindow(window) diff --git a/sources/pyside2/doc/codesnippets/examples/mainwindows/menus/mainwindow.cpp b/sources/pyside2/doc/codesnippets/examples/mainwindows/menus/mainwindow.py index 6ed5f5466..6505f1f1a 100644 --- a/sources/pyside2/doc/codesnippets/examples/mainwindows/menus/mainwindow.cpp +++ b/sources/pyside2/doc/codesnippets/examples/mainwindows/menus/mainwindow.py @@ -196,63 +196,63 @@ def createActions(self): Act = new QAction(tr("&New"), self) Act.setShortcuts(QKeySequence.New) Act.setStatusTip(tr("Create a new file")) - connect(Act, SIGNAL("triggered()"), self, SLOT("newFile()")) + Act.triggered.connect(newFile) //! [4] openAct = QAction(tr("&Open..."), self) openAct.setShortcuts(QKeySequence.Open) openAct.setStatusTip(tr("Open an existing file")) - connect(openAct, SIGNAL("triggered()"), self, SLOT("open()")) + openAct.triggered.connect(open) //! [5] saveAct = QAction(tr("&Save"), self) saveAct.setShortcuts(QKeySequence.Save) saveAct.setStatusTip(tr("Save the document to disk")) - connect(saveAct, SIGNAL("triggered()"), self, SLOT("save()")) + saveAct.triggered.connect(save) printAct = QAction(tr("&Print..."), self) printAct.setShortcuts(QKeySequence.Print) printAct.setStatusTip(tr("Print the document")) - connect(printAct, SIGNAL("triggered()"), self, SLOT("print_()")) + printAct.triggered.connect(print_) exitAct = QAction(tr("E&xit"), self) exitAct.setShortcut(tr("Ctrl+Q")) exitAct.setStatusTip(tr("Exit the application")) - connect(exitAct, SIGNAL("triggered()"), self, SLOT("close()")) + exitAct.triggered.connect(close) undoAct = QAction(tr("&Undo"), self) undoAct.setShortcuts(QKeySequence.Undo) undoAct.setStatusTip(tr("Undo the last operation")) - connect(undoAct, SIGNAL("triggered()"), self, SLOT("undo()")) + undoAct.triggered.connect(undo) redoAct = QAction(tr("&Redo"), self) redoAct.setShortcuts(QKeySequence.Redo) redoAct.setStatusTip(tr("Redo the last operation")) - connect(redoAct, SIGNAL("triggered()"), self, SLOT("redo()")) + redoAct.triggered.connect(redo) cutAct = QAction(tr("Cu&t"), self) cutAct.setShortcuts(QKeySequence.Cut) cutAct.setStatusTip(tr("Cut the current selection's contents to the " "clipboard")) - connect(cutAct, SIGNAL("triggered()"), self, SLOT("cut()")) + cutAct.triggered.connect(cut) copyAct = QAction(tr("&Copy"), self) copyAct.setShortcut(tr("Ctrl+C")) copyAct.setStatusTip(tr("Copy the current selection's contents to the " "clipboard")) - connect(copyAct, SIGNAL("triggered()"), self, SLOT("copy()")) + copyAct.triggered.connect(copy) pasteAct = QAction(tr("&Paste"), self) pasteAct.setShortcuts(QKeySequence.Paste) pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " "selection")) - connect(pasteAct, SIGNAL("triggered()"), self, SLOT("paste()")) + pasteAct.triggered.connect(paste) boldAct = QAction(tr("&Bold"), self) boldAct.setCheckable(True) boldAct.setShortcut(tr("Ctrl+B")) boldAct.setStatusTip(tr("Make the text bold")) - connect(boldAct, SIGNAL("triggered()"), self, SLOT("bold()")) + boldAct.triggered.connect(bold) QFont boldFont = boldAct.font() boldFont.setBold(True) @@ -262,7 +262,7 @@ def createActions(self): italicAct.setCheckable(True) italicAct.setShortcut(tr("Ctrl+I")) italicAct.setStatusTip(tr("Make the text italic")) - connect(italicAct, SIGNAL("triggered()"), self, SLOT("italic()")) + italicAct.triggered.connect(italic) QFont italicFont = italicAct.font() italicFont.setItalic(True) @@ -271,45 +271,44 @@ def createActions(self): setLineSpacingAct = QAction(tr("Set &Line Spacing..."), self) setLineSpacingAct.setStatusTip(tr("Change the gap between the lines of a " "paragraph")) - connect(setLineSpacingAct, SIGNAL("triggered()"), self, SLOT("setLineSpacing()")) + setLineSpacingAct.triggered.connect(setLineSpacing) setParagraphSpacingAct = QAction(tr("Set &Paragraph Spacing..."), self) setLineSpacingAct.setStatusTip(tr("Change the gap between paragraphs")) - connect(setParagraphSpacingAct, SIGNAL("triggered()"), - self, SLOT("setParagraphSpacing()")) + setParagraphSpacingAct.triggered.connect(setParagraphSpacing) aboutAct = QAction(tr("&About"), self) aboutAct.setStatusTip(tr("Show the application's About box")) - connect(aboutAct, SIGNAL("triggered()"), self, SLOT("about()")) + aboutAct.triggered.connect(about) aboutQtAct = QAction(tr("About &Qt"), self) aboutQtAct.setStatusTip(tr("Show the Qt library's About box")) - connect(aboutQtAct, SIGNAL("triggered()"), qApp, SLOT("aboutQt()")) - connect(aboutQtAct, SIGNAL("triggered()"), self, SLOT("aboutQt()")) + aboutQtAct.triggered.connect(qApp.aboutQt) + aboutQtAct.triggered.connect(aboutQt) leftAlignAct = QAction(tr("&Left Align"), self) leftAlignAct.setCheckable(True) leftAlignAct.setShortcut(tr("Ctrl+L")) leftAlignAct.setStatusTip(tr("Left align the selected text")) - connect(leftAlignAct, SIGNAL("triggered()"), self, SLOT("leftAlign()")) + leftAlignAct.triggered.connect(leftAlign) rightAlignAct = QAction(tr("&Right Align"), self) rightAlignAct.setCheckable(True) rightAlignAct.setShortcut(tr("Ctrl+R")) rightAlignAct.setStatusTip(tr("Right align the selected text")) - connect(rightAlignAct, SIGNAL("triggered()"), self, SLOT("rightAlign()")) + rightAlignAct.triggered.connect(rightAlign) justifyAct = QAction(tr("&Justify"), self) justifyAct.setCheckable(True) justifyAct.setShortcut(tr("Ctrl+J")) justifyAct.setStatusTip(tr("Justify the selected text")) - connect(justifyAct, SIGNAL("triggered()"), self, SLOT("justify()")) + justifyAct.triggered.connect(justify) centerAct = QAction(tr("&Center"), self) centerAct.setCheckable(True) centerAct.setShortcut(tr("Ctrl+E")) centerAct.setStatusTip(tr("Center the selected text")) - connect(centerAct, SIGNAL("triggered()"), self, SLOT("center()")) + centerAct.triggered.connect(center) //! [6] //! [7] alignmentGroup = QActionGroup(self) diff --git a/sources/pyside2/doc/codesnippets/examples/widgets/spinboxes/window.cpp b/sources/pyside2/doc/codesnippets/examples/widgets/spinboxes/window.py index 7eace108a..40fe28bf1 100644 --- a/sources/pyside2/doc/codesnippets/examples/widgets/spinboxes/window.cpp +++ b/sources/pyside2/doc/codesnippets/examples/widgets/spinboxes/window.py @@ -147,8 +147,7 @@ def createDateTimeEdits(self): formatComboBox.addItem("hh:mm ap") //! [9] //! [10] - connect(formatComboBox, SIGNAL("activated(const QString &)"), - self, SLOT("setFormatString(const QString &)")) + formatComboBox.activated[str].connect(setFormatString) //! [10] setFormatString(formatComboBox.currentText()) @@ -174,12 +173,12 @@ def setFormatString(self, formatString): meetingEdit.setDateRange(QDate(2004, 11, 1), QDate(2005, 11, 30)) meetingLabel.setText(tr("Meeting date (between %0 and %1):") .arg(meetingEdit.minimumDate().toString(Qt.ISODate)) - .arg(meetingEdit.maximumDate().toString(Qt.ISODate))) + .arg(meetingEdit.maximumDate().toString(Qt.ISODate))) else: meetingEdit.setTimeRange(QTime(0, 7, 20, 0), QTime(21, 0, 0, 0)) meetingLabel.setText(tr("Meeting time (between %0 and %1):") .arg(meetingEdit.minimumTime().toString(Qt.ISODate)) - .arg(meetingEdit.maximumTime().toString(Qt.ISODate))) + .arg(meetingEdit.maximumTime().toString(Qt.ISODate))) //! [13] //! [14] @@ -222,9 +221,8 @@ def createDoubleSpinBoxes(): priceSpinBox.setPrefix("$") priceSpinBox.setValue(99.99) - connect(precisionSpinBox, SIGNAL("valueChanged(int)"), + precisionSpinBox.valueChanged[int].connect(changePrecision) //! [17] - self, SLOT("changePrecision(int))") //! [18] spinBoxLayout = QVBoxLayout() diff --git a/sources/pyside2/doc/conf.py.in b/sources/pyside2/doc/conf.py.in index e197b1ac7..e37abcb24 100644 --- a/sources/pyside2/doc/conf.py.in +++ b/sources/pyside2/doc/conf.py.in @@ -31,6 +31,11 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.graphviz', 'inheritance_diagram', 'pysideinclude', 'sphinx.ext.viewcode'] +output_format='@DOC_OUTPUT_FORMAT@' + +def setup(app): + app.add_config_value('output_format','qthelp','env') + rst_epilog = """ .. |project| replace:: Qt for Python .. |pymodname| replace:: PySide2 @@ -170,6 +175,10 @@ html_show_sourcelink = False # Link to the shiboken2 sphinx project to enable linking # between the two projects. -intersphinx_mapping = {'shiboken2': ('shiboken2','@CMAKE_BINARY_DIR@/../shiboken2/doc/html/objects.inv')} +intersphinx_mapping = {'shiboken2': ('shiboken2','@CMAKE_BINARY_DIR@/doc/html/shiboken2/doc/html/objects.inv')} add_module_names = False + +# -- Options for qthelp output --------------------------------------------------- +qthelp_theme = 'pysidedocs_qthelp' + diff --git a/sources/pyside2/doc/extras/QtCore.QEnum.rst b/sources/pyside2/doc/extras/QtCore.QEnum.rst new file mode 100644 index 000000000..a5a2e31fd --- /dev/null +++ b/sources/pyside2/doc/extras/QtCore.QEnum.rst @@ -0,0 +1,92 @@ +.. currentmodule:: PySide2.QtCore +.. _QEnum: + +QEnum/QFlag +*********** + +This class decorator is equivalent to the `Q_ENUM` macro from Qt. +The decorator is used to register an Enum to the meta-object system, +which is available via `QObject.staticMetaObject`. +The enumerator must be in a QObject derived class to be registered. + + +Example +------- + +:: + + from enum import Enum, Flag, auto + + from PySide2.QtCore import QEnum, QFlag, QObject + + class Demo(QObject): + + @QEnum + class Orientation(Enum): + North, East, South, West = range(4) + + class Color(Flag): + RED = auto() + BLUE = auto() + GREEN = auto() + WHITE = RED | BLUE | GREEN + + QFlag(Color) # identical to @QFlag usage + + +Caution: +-------- + +QEnum registers a Python Enum derived class. +QFlag treats a variation of the Python Enum, the Flag class. + +Please do not confuse that with the Qt QFlags concept. Python does +not use that concept, it has its own class hierarchy, instead. +For more details, see the `Python enum documentation <https://docs.python.org/3/library/enum.html>`_. + + +Details about Qt Flags: +----------------------- + +There are some small differences between Qt flags and Python flags. +In Qt, we have for instance these declarations: + +:: + + enum QtGui::RenderHint { Antialiasing, TextAntialiasing, SmoothPixmapTransform, + HighQualityAntialiasing, NonCosmeticDefaultPen } + flags QtGui::RenderHints + +The equivalent Python notation would look like this: + +:: + + @QFlag + class RenderHints(enum.Flag) + Antialiasing = auto() + TextAntialiasing = auto() + SmoothPixmapTransform = auto() + HighQualityAntialiasing = auto() + NonCosmeticDefaultPen = auto() + + +As another example, the Qt::AlignmentFlag flag has 'AlignmentFlag' as the enum +name, but 'Alignment' as the type name. Non flag enums have the same type and +enum names. + +:: + + enum Qt::AlignmentFlag + flags Qt::Alignment + +The Python way to specify this would be + +:: + + @QFlag + class Alignment(enum.Flag): + ... + +We are considering to map all builtin enums and flags to Python enums as well +in a later release. + diff --git a/sources/pyside2/doc/extras/QtUiTools.loadUiType.rst b/sources/pyside2/doc/extras/QtUiTools.loadUiType.rst new file mode 100644 index 000000000..9ca330dea --- /dev/null +++ b/sources/pyside2/doc/extras/QtUiTools.loadUiType.rst @@ -0,0 +1,36 @@ +.. currentmodule:: PySide2.QtUiTools +.. _loadUiType: + +loadUiType +*********** + +.. py:function:: loadUiType(uifile: str) -> tuple(object, object) + + :param str uifile: The name of the `.ui` file + :return: tuple(object, object) + + This function generates and loads a `.ui` file at runtime, and it returns + a `tuple` containing the reference to the Python class, and the base class. + + We recommend not to use this approach as the workflow should be to generate a Python file + from the `.ui` file, and then import and load it to use it, but we do understand that + there are some corner cases when such functionality is required. + + The internal process relies on `uic` being in the PATH. + The `pyside2-uic` wrapper uses a shipped `uic` that is located in the + `site-packages/PySide2/uic`, so PATH needs to be updated to use that if there + is no `uic` in the system. + + A simple use case is:: + + from PySide2.QtUiTools import loadUiType + + generated_class, base_class = loadUiType("themewidget.ui") + # the values will be: + # (<class '__main__.Ui_ThemeWidgetForm'>, <class 'PySide2.QtWidgets.QWidget'>) + + widget = base_class() + form = generated_class() + form.setupUi(widget) + # form.a_widget_member.a_method_of_member() + widget.show() diff --git a/sources/pyside2/doc/extras/QtUiTools.rst b/sources/pyside2/doc/extras/QtUiTools.rst index 553224527..598d69dda 100644 --- a/sources/pyside2/doc/extras/QtUiTools.rst +++ b/sources/pyside2/doc/extras/QtUiTools.rst @@ -6,4 +6,4 @@ To include the definitions of the module's classes, use the following directive: :: - import PySide..QtUiTools + import PySide.QtUiTools diff --git a/sources/pyside2/doc/gettingstarted.rst b/sources/pyside2/doc/gettingstarted.rst index dbe22a806..b8d6f9e45 100644 --- a/sources/pyside2/doc/gettingstarted.rst +++ b/sources/pyside2/doc/gettingstarted.rst @@ -63,7 +63,8 @@ Other important options to consider are: * ``--reuse-build``, to rebuild only the modified files, * ``--openssl=/path/to/openssl/bin``, to use a different path for OpenSSL, * ``--standalone``, to copy over the Qt libraries into the final package - to make it work on other machines. + to make it work on other machines, + * ``--doc-build-online``, to build documentation using the online template. Testing the installation ------------------------- @@ -110,7 +111,32 @@ directory, and run:: make apidoc -Finally, you will get a ``html`` directory containing all the generated documentation. +.. note:: The ``apidoc`` make target builds offline documenation in QCH (Qt Creator Help) format + by default. You can switch to building for the online use with the ``--doc-build-online`` + configure option. + +Finally, you will get a ``html`` directory containing all the generated documentation. The offline +help files, ``PySide.qch`` and ``Shiboken.qch``, can be moved to any directory of your choice. You +can find ``Shiboken.qch`` in the build directory, ``*_build\*_release\shiboken2\doc\html``. + +Viewing offline documentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The offline documentation (QCH) can be viewed using the Qt Creator IDE or Qt Assistant, which is +a standalone application for viewing QCH files. + +To view the QCH using Qt Creator, following the instructions outlined in +`Using Qt Creator Help Mode <https://doc.qt.io/qtcreator/creator-help.html>`_. If you chose to +use Qt Assistant instead, use the following command to register the QCH file before launching +Qt Assistant: + + assistant -register PySide.qch + +.. note:: Qt Assistant renders the QCH content using the QTextBrowser backend, which supports + a subset of the CSS styles, However, Qt Creator offers an alternative litehtml-based + backend, which offers better browsing experience. At the moment, this is not the default + backend, so you have to select the litehtml backend + explicitly under the ``General`` tab in ``Qt Creator >> Tools >> Options >> Help``. Using the internal tools ------------------------ diff --git a/sources/pyside2/doc/index.rst b/sources/pyside2/doc/index.rst index 96cbf2ab2..72a26d19d 100644 --- a/sources/pyside2/doc/index.rst +++ b/sources/pyside2/doc/index.rst @@ -1,45 +1,84 @@ |project| ********* -**Qt for Python** offers the official Python bindings for `Qt`_ (`PySide2`_), -so that you can use Qt5 APIs in your Python applications, and a binding generator tool (`Shiboken2`_) -which can be used to expose C++ projects into Python. +.. ifconfig:: output_format == 'html' + + **Qt for Python** offers the official Python bindings for `Qt`_ (`PySide2`_), + so that you can use Qt5 APIs in your Python applications, and a binding generator tool + (`Shiboken2 <shiboken2/index.html>`_) which can be used to expose C++ projects into Python. + +.. ifconfig:: output_format == 'qthelp' + + **Qt for Python** offers the official Python bindings for `Qt`_ (`PySide2`_), + so that you can use Qt5 APIs in your Python applications, and a binding generator tool + (`Shiboken2 <../shiboken2/index.html>`_) which can be used to expose C++ projects into Python. |project| is available under the LGPLv3/GPLv3 and the Qt commercial license. .. _Qt: https://doc.qt.io .. _PySide2: quickstart.html -.. _Shiboken2: shiboken2/index.html + Documentation ============= -.. raw:: html - - <table class="special"> - <colgroup> - <col style="width: 33%" /> - <col style="width: 33%" /> - <col style="width: 33%" /> - </colgroup> - <tr> - <td><a href="quickstart.html"><p><strong>Check It Out!</strong><br/>Write your first Qt app.</p></a></td> - <td><a href="gettingstarted.html"><p><strong>Getting Started</strong><br/>Install and build from source.</p></a></td> - <td><a href="api.html"><p><strong>API Docs</strong><br/>Qt for Python API reference.</p></a></td> - </tr> - - <tr> - <td><a href="tutorials/index.html"><p><strong>Tutorials</strong><br/>Learn with step-by-step guides.</p></a></td> - <td><a href="examples/index.html"><p><strong>Examples</strong><br/>Check all the available examples.</p></a></td> - <td><a href="videos.html"><p><strong>Videos</strong><br/>Watch webinars, Talks, and more.</p></a></td> - </tr> - - <tr> - <td><a href="deployment.html" style="display: block;"><p><strong>Deployment</strong><br/>Learn to deploy your apps.</p></a></td> - <td><a href="considerations.html" style="display: block;"><p><strong>Considerations</strong><br/>API differences and known issues.</p></a></td> - <td><a href="shiboken2/index.html" style="display: block;"><p><strong>Shiboken</strong><br/>Generate C++ to Python binding.</p></a></td> - </tr> - </table> +.. ifconfig:: output_format == 'html' + + .. raw:: html + + <table class="special"> + <colgroup> + <col style="width: 33%" /> + <col style="width: 33%" /> + <col style="width: 33%" /> + </colgroup> + <tr> + <td><a href="quickstart.html"><p><strong>Check It Out!</strong><br/>Write your first Qt app.</p></a></td> + <td><a href="gettingstarted.html"><p><strong>Getting Started</strong><br/>Install and build from source.</p></a></td> + <td><a href="api.html"><p><strong>API Docs</strong><br/>Qt for Python API reference.</p></a></td> + </tr> + + <tr> + <td><a href="tutorials/index.html"><p><strong>Tutorials</strong><br/>Learn with step-by-step guides.</p></a></td> + <td><a href="examples/index.html"><p><strong>Examples</strong><br/>Check all the available examples.</p></a></td> + <td><a href="videos.html"><p><strong>Videos</strong><br/>Watch webinars, Talks, and more.</p></a></td> + </tr> + + <tr> + <td><a href="deployment.html" style="display: block;"><p><strong>Deployment</strong><br/>Learn to deploy your apps.</p></a></td> + <td><a href="considerations.html" style="display: block;"><p><strong>Considerations</strong><br/>API differences and known issues.</p></a></td> + <td><a href="shiboken2/index.html" style="display: block;"><p><strong>Shiboken</strong><br/>Generate C++ to Python binding.</p></a></td> + </tr> + </table> + +.. ifconfig :: output_format == 'qthelp' + + .. raw:: html + + <table class="special"> + <colgroup> + <col style="width: 33%" /> + <col style="width: 33%" /> + <col style="width: 33%" /> + </colgroup> + <tr> + <td><a href="quickstart.html"><p><strong>Check It Out!</strong><br/>Write your first Qt app.</p></a></td> + <td><a href="gettingstarted.html"><p><strong>Getting Started</strong><br/>Install and build from source.</p></a></td> + <td><a href="api.html"><p><strong>API Docs</strong><br/>Qt for Python API reference.</p></a></td> + </tr> + + <tr> + <td><a href="tutorials/index.html"><p><strong>Tutorials</strong><br/>Learn with step-by-step guides.</p></a></td> + <td><a href="examples/index.html"><p><strong>Examples</strong><br/>Check all the available examples.</p></a></td> + <td><a href="videos.html"><p><strong>Videos</strong><br/>Watch webinars, Talks, and more.</p></a></td> + </tr> + + <tr> + <td><a href="deployment.html" style="display: block;"><p><strong>Deployment</strong><br/>Learn to deploy your apps.</p></a></td> + <td><a href="considerations.html" style="display: block;"><p><strong>Considerations</strong><br/>API differences and known issues.</p></a></td> + <td><a href="../shiboken2/index.html" style="display: block;"><p><strong>Shiboken</strong><br/>Generate C++ to Python binding.</p></a></td> + </tr> + </table> .. toctree:: :hidden: diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons.png b/sources/pyside2/doc/tutorials/basictutorial/icons.png Binary files differnew file mode 100644 index 000000000..0bcfd7d77 --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons/forward.png b/sources/pyside2/doc/tutorials/basictutorial/icons/forward.png Binary files differnew file mode 100644 index 000000000..c7a532dfe --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons/forward.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons/pause.png b/sources/pyside2/doc/tutorials/basictutorial/icons/pause.png Binary files differnew file mode 100644 index 000000000..d0beadb43 --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons/pause.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons/play.png b/sources/pyside2/doc/tutorials/basictutorial/icons/play.png Binary files differnew file mode 100644 index 000000000..345685337 --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons/play.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons/previous.png b/sources/pyside2/doc/tutorials/basictutorial/icons/previous.png Binary files differnew file mode 100644 index 000000000..979f18565 --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons/previous.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/icons/stop.png b/sources/pyside2/doc/tutorials/basictutorial/icons/stop.png Binary files differnew file mode 100644 index 000000000..1e88ded3a --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/icons/stop.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/player-new.png b/sources/pyside2/doc/tutorials/basictutorial/player-new.png Binary files differnew file mode 100644 index 000000000..e1f660e5f --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/player-new.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/player.png b/sources/pyside2/doc/tutorials/basictutorial/player.png Binary files differnew file mode 100644 index 000000000..3060a990d --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/player.png diff --git a/sources/pyside2/doc/tutorials/basictutorial/qrcfiles.rst b/sources/pyside2/doc/tutorials/basictutorial/qrcfiles.rst new file mode 100644 index 000000000..2f986875c --- /dev/null +++ b/sources/pyside2/doc/tutorials/basictutorial/qrcfiles.rst @@ -0,0 +1,169 @@ +Using `.qrc` Files (`pyside2-rcc`) +********************************** + +The `Qt Resource System`_ is a mechanism for storing binary files +in an application. + +The most common uses are for custom images, icons, fonts, among others. + +In this tutorial you will learn how to load custom images as button icons. + +For inspiration, we will try to adapt the multimedia player example +from Qt. + +As you can see on the following image, the `QPushButton` that are used +for the media actions (play, pause, stop, and so on) are using the +default icons meant for such actions. + +.. image:: player.png + :alt: Multimedia Player Qt Example + +You could make the application more attractive by designing the icons, +but in case you don't want to design them, `download the following set`_ +and use them. + +.. image:: icons.png + :alt: New Multimedia icons + +You can find more information about the `rcc` command, and `.qrc` file +format, and the resource system in general in the `Qt Resource System`_ +site. + +.. _`download the following set`: icons/ + + +The `.qrc` file +================ + +Before running any command, add information about the resources to a `.qrc` +file. +In the following example, notice how the resources are listed in `icons.qrc` + +:: + + </ui> + <!DOCTYPE RCC><RCC version="1.0"> + <qresource> + <file>icons/play.png</file> + <file>icons/pause.png</file> + <file>icons/stop.png</file> + <file>icons/previous.png</file> + <file>icons/forward.png</file> + </qresource> + </RCC> + + +Generating a Python file +========================= + +Now that the `icons.qrc` file is ready, use the `pyside2-rcc` tool to generate +a Python class containing the binary information about the resources + +To do this, we need to run:: + + pyside2-rcc icons.rc -o rc_icons.py + +The `-o` option lets you specify the output filename, +which is `rc_icons.py` in this case. + +To use the generated file, add the following import at the top of your main Python file:: + + import rc_icons + + +Changes in the code +=================== + +As you are modifying an existing example, you need to modify the following +lines: + +.. code-block:: python + + from PySide2.QtGui import QIcon, QKeySequence + playIcon = self.style().standardIcon(QStyle.SP_MediaPlay) + previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward) + pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause) + nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward) + stopIcon = self.style().standardIcon(QStyle.SP_MediaStop) + +and replace them with the following: + +.. code-block:: python + + from PySide2.QtGui import QIcon, QKeySequence, QPixmap + playIcon = QIcon(QPixmap(":/icons/play.png")) + previousIcon = QIcon(QPixmap(":/icons/previous.png")) + pauseIcon = QIcon(QPixmap(":/icons/pause.png")) + nextIcon = QIcon(QPixmap(":/icons/forward.png")) + stopIcon = QIcon(QPixmap(":/icons/stop.png")) + +This ensures that the new icons are used instead of the default ones provided +by the application theme. +Notice that the lines are not consecutive, but are in different parts +of the file. + +After all your imports, add the following + +.. code-block:: python + + import rc_icons + +Now, the constructor of your class should look like this: + +.. code-block:: python + + def __init__(self): + super(MainWindow, self).__init__() + + self.playlist = QMediaPlaylist() + self.player = QMediaPlayer() + + toolBar = QToolBar() + self.addToolBar(toolBar) + + fileMenu = self.menuBar().addMenu("&File") + openAction = QAction(QIcon.fromTheme("document-open"), + "&Open...", self, shortcut=QKeySequence.Open, + triggered=self.open) + fileMenu.addAction(openAction) + exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit", + self, shortcut="Ctrl+Q", triggered=self.close) + fileMenu.addAction(exitAction) + + playMenu = self.menuBar().addMenu("&Play") + playIcon = QIcon(QPixmap(":/icons/play.png")) + self.playAction = toolBar.addAction(playIcon, "Play") + self.playAction.triggered.connect(self.player.play) + playMenu.addAction(self.playAction) + + previousIcon = QIcon(QPixmap(":/icons/previous.png")) + self.previousAction = toolBar.addAction(previousIcon, "Previous") + self.previousAction.triggered.connect(self.previousClicked) + playMenu.addAction(self.previousAction) + + pauseIcon = QIcon(QPixmap(":/icons/pause.png")) + self.pauseAction = toolBar.addAction(pauseIcon, "Pause") + self.pauseAction.triggered.connect(self.player.pause) + playMenu.addAction(self.pauseAction) + + nextIcon = QIcon(QPixmap(":/icons/forward.png")) + self.nextAction = toolBar.addAction(nextIcon, "Next") + self.nextAction.triggered.connect(self.playlist.next) + playMenu.addAction(self.nextAction) + + stopIcon = QIcon(QPixmap(":/icons/stop.png")) + self.stopAction = toolBar.addAction(stopIcon, "Stop") + self.stopAction.triggered.connect(self.player.stop) + playMenu.addAction(self.stopAction) + + # many lines were omitted + +Executing the example +===================== + +Run the application by calling `python main.py` to checkout the new icon-set: + +.. image:: player-new.png + :alt: New Multimedia Player Qt Example + +.. _`Qt Resource System`: https://doc.qt.io/qt-5/resources.html diff --git a/sources/pyside2/doc/tutorials/basictutorial/uifiles.rst b/sources/pyside2/doc/tutorials/basictutorial/uifiles.rst index 2c0178e2e..804905eb8 100644 --- a/sources/pyside2/doc/tutorials/basictutorial/uifiles.rst +++ b/sources/pyside2/doc/tutorials/basictutorial/uifiles.rst @@ -1,5 +1,5 @@ -Using UI Files -*************** +Using `.ui` Files (`QUiLoader` and `pyside2-uic`) +************************************************* This page describes the use of Qt Creator to create graphical interfaces for your Qt for Python project. @@ -158,7 +158,7 @@ The complete code of this example looks like this: import sys from PySide2.QtUiTools import QUiLoader from PySide2.QtWidgets import QApplication - from PySide2.QtCore import QFile + from PySide2.QtCore import QFile, QIODevice if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/sources/pyside2/doc/tutorials/expenses/expenses.rst b/sources/pyside2/doc/tutorials/expenses/expenses.rst index f643ec299..640feb487 100644 --- a/sources/pyside2/doc/tutorials/expenses/expenses.rst +++ b/sources/pyside2/doc/tutorials/expenses/expenses.rst @@ -3,12 +3,12 @@ Expenses Tool Tutorial ###################### In this tutorial you will learn the following concepts: -* creating user interfaces programatically, -* layouts and widgets, -* overloading Qt classes, -* connecting signal and slots, -* interacting with QWidgets, -* and building your own application. + * creating user interfaces programatically, + * layouts and widgets, + * overloading Qt classes, + * connecting signal and slots, + * interacting with QWidgets, + * and building your own application. The requirements: * A simple window for the application diff --git a/sources/pyside2/doc/tutorials/index.rst b/sources/pyside2/doc/tutorials/index.rst index 73e6b6b26..598b42ca1 100644 --- a/sources/pyside2/doc/tutorials/index.rst +++ b/sources/pyside2/doc/tutorials/index.rst @@ -18,6 +18,7 @@ Basic tutorials basictutorial/clickablebutton.rst basictutorial/dialog.rst basictutorial/uifiles.rst + basictutorial/qrcfiles.rst Real use-cases applications --------------------------- diff --git a/sources/pyside2/doc/videos.rst b/sources/pyside2/doc/videos.rst index cda84f419..511bc0d66 100644 --- a/sources/pyside2/doc/videos.rst +++ b/sources/pyside2/doc/videos.rst @@ -15,7 +15,7 @@ Webinar: Creating user interfaces with Qt for Python </div> Webinar: Develop your first Qt for Python application ------------------------------------------------------- +----------------------------------------------------- .. raw:: html @@ -26,3 +26,68 @@ Webinar: Develop your first Qt for Python application width: 100%; height: 100%;"> </iframe> </div> + +Webinar: Python and C++ interoperability with Shiboken +------------------------------------------------------ + +.. raw:: html + + <div style="position: relative; padding-bottom: 56.25%; height: 0; + overflow: hidden; max-width: 100%; height: auto;"> + <iframe src="https://www.youtube.com/embed/wOMlDutOWXI" frameborder="0" + allowfullscreen style="position: absolute; top: 0; left: 0; + width: 100%; height: 100%;"> + </iframe> + </div> + +QtWS2018: Mastering Qt for Python in 20 min +-------------------------------------------- + +.. raw:: html + + <div style="position: relative; padding-bottom: 56.25%; height: 0; + overflow: hidden; max-width: 100%; height: auto;"> + <iframe src="https://www.youtube.com/embed/IhxZ99usPqY" frameborder="0" + allowfullscreen style="position: absolute; top: 0; left: 0; + width: 100%; height: 100%;"> + </iframe> + </div> + +QtWS2019: Utilizing Shiboken to Enhance your Qt for Python Application +---------------------------------------------------------------------- + +.. raw:: html + + <div style="position: relative; padding-bottom: 56.25%; height: 0; + overflow: hidden; max-width: 100%; height: auto;"> + <iframe src="https://www.youtube.com/embed/mAfEVPgHRt8" frameborder="0" + allowfullscreen style="position: absolute; top: 0; left: 0; + width: 100%; height: 100%;"> + </iframe> + </div> + +QtWS2019: Introduction to Qt for Python +--------------------------------------- + +.. raw:: html + + <div style="position: relative; padding-bottom: 56.25%; height: 0; + overflow: hidden; max-width: 100%; height: auto;"> + <iframe src="https://www.youtube.com/embed/214TWASZVgA" frameborder="0" + allowfullscreen style="position: absolute; top: 0; left: 0; + width: 100%; height: 100%;"> + </iframe> + </div> + +QtWS2019: How to bring your C++ project to Python land +------------------------------------------------------ + +.. raw:: html + + <div style="position: relative; padding-bottom: 56.25%; height: 0; + overflow: hidden; max-width: 100%; height: auto;"> + <iframe src="https://www.youtube.com/embed/XmY-tWTi9gY" frameborder="0" + allowfullscreen style="position: absolute; top: 0; left: 0; + width: 100%; height: 100%;"> + </iframe> + </div> diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt index 7493a453a..31f68749a 100644 --- a/sources/pyside2/libpyside/CMakeLists.txt +++ b/sources/pyside2/libpyside/CMakeLists.txt @@ -1,33 +1,33 @@ project(libpyside) -if(${Qt5Qml_FOUND}) - if(NOT "${Qt5Qml_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQml/") - string(REPLACE "/QtCore" "/QtQml" replaceme "${Qt5Core_PRIVATE_INCLUDE_DIRS}") - list(APPEND Qt5Qml_PRIVATE_INCLUDE_DIRS ${replaceme}) - list(REMOVE_DUPLICATES Qt5Qml_PRIVATE_INCLUDE_DIRS) +if(${Qt${QT_MAJOR_VERSION}Qml_FOUND}) + if(NOT "${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQml/") + string(REPLACE "/QtCore" "/QtQml" replaceme "${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS}") + list(APPEND Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS ${replaceme}) + list(REMOVE_DUPLICATES Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS) endif() endif() -if(${Qt5Quick_FOUND}) - if(NOT "${Qt5Quick_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQuick/") - string(REPLACE "/QtCore" "/QtQuick" replaceme "${Qt5Core_PRIVATE_INCLUDE_DIRS}") - list(APPEND Qt5Quick_PRIVATE_INCLUDE_DIRS ${Qt5Qml_PRIVATE_INCLUDE_DIRS}) - list(APPEND Qt5Quick_PRIVATE_INCLUDE_DIRS ${replaceme}) - list(REMOVE_DUPLICATES Qt5Quick_PRIVATE_INCLUDE_DIRS) +if(${Qt${QT_MAJOR_VERSION}Quick_FOUND}) + if(NOT "${Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQuick/") + string(REPLACE "/QtCore" "/QtQuick" replaceme "${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS}") + list(APPEND Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS ${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}) + list(APPEND Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS ${replaceme}) + list(REMOVE_DUPLICATES Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS) endif() endif() set(QML_PRIVATE_API_SUPPORT 0) -if(Qt5Qml_FOUND) +if(Qt${QT_MAJOR_VERSION}Qml_FOUND) # Used for registering custom QQuickItem classes defined in Python code. set(QML_SUPPORT 1) - set(QML_INCLUDES ${Qt5Qml_INCLUDE_DIRS}) - set(QML_LIBRARIES ${Qt5Qml_LIBRARIES}) + set(QML_INCLUDES ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS}) + set(QML_LIBRARIES ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES}) - if(Qt5Qml_PRIVATE_INCLUDE_DIRS) + if(Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS) # Used for transforming QML exceptions into Python exceptions. set(QML_PRIVATE_API_SUPPORT 1) - set(QML_INCLUDES ${QML_INCLUDES} ${Qt5Qml_PRIVATE_INCLUDE_DIRS}) + set(QML_INCLUDES ${QML_INCLUDES} ${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}) else() message(WARNING "QML private API include files could not be found, support for catching QML exceptions inside Python code will not work.") endif() @@ -38,14 +38,12 @@ else() set(QML_LIBRARIES "") endif() -qt5_wrap_cpp(DESTROYLISTENER_MOC "destroylistener.h") - set(libpyside_SRC dynamicqmetaobject.cpp - destroylistener.cpp signalmanager.cpp globalreceiverv2.cpp pysideclassinfo.cpp + pysideqenum.cpp pysidemetafunction.cpp pysidesignal.cpp pysideslot.cpp @@ -54,7 +52,6 @@ set(libpyside_SRC pysideweakref.cpp pyside.cpp pysidestaticstrings.cpp - ${DESTROYLISTENER_MOC} ) # Add python files to project explorer in Qt Creator, when opening the CMakeLists.txt as a project, @@ -84,8 +81,8 @@ add_library(PySide2::pyside2 ALIAS pyside2) target_include_directories(pyside2 PRIVATE ${QML_INCLUDES} - ${Qt5Core_PRIVATE_INCLUDE_DIRS} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} ) target_include_directories(pyside2 PUBLIC @@ -96,7 +93,7 @@ target_include_directories(pyside2 PUBLIC target_link_libraries(pyside2 PRIVATE Shiboken2::libshiboken PRIVATE ${QML_LIBRARIES} - PRIVATE ${Qt5Core_LIBRARIES}) + PRIVATE ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES}) set_target_properties(pyside2 PROPERTIES VERSION ${BINDING_API_VERSION} @@ -104,7 +101,9 @@ set_target_properties(pyside2 PROPERTIES OUTPUT_NAME "pyside2${pyside2_SUFFIX}${SHIBOKEN_PYTHON_SHARED_LIBRARY_SUFFIX}" DEFINE_SYMBOL PYSIDE_EXPORTS) -if(Qt5Core_VERSION VERSION_GREATER "5.7.1") +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + set_property(TARGET pyside2 PROPERTY CXX_STANDARD 17) +else() set_property(TARGET pyside2 PROPERTY CXX_STANDARD 11) endif() @@ -125,9 +124,9 @@ endif() # set(libpyside_HEADERS - destroylistener.h dynamicqmetaobject.h pysideclassinfo.h + pysideqenum.h pysidemacros.h signalmanager.h pyside.h diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.cpp b/sources/pyside2/libpyside/dynamicqmetaobject.cpp index dae9e2059..efdf33ac9 100644 --- a/sources/pyside2/libpyside/dynamicqmetaobject.cpp +++ b/sources/pyside2/libpyside/dynamicqmetaobject.cpp @@ -44,6 +44,7 @@ #include "pysideproperty.h" #include "pysideproperty_p.h" #include "pysideslot_p.h" +#include "pysideqenum.h" #include <shiboken.h> @@ -91,6 +92,10 @@ public: int addProperty(const QByteArray &property, PyObject *data); void addInfo(const QByteArray &key, const QByteArray &value); void addInfo(const QMap<QByteArray, QByteArray> &info); + void addEnumerator(const char *name, + bool flag, + bool scoped, + const QVector<QPair<QByteArray, int> > &entries); void removeProperty(int index); const QMetaObject *update(); @@ -357,6 +362,28 @@ void MetaObjectBuilder::addInfo(const QMap<QByteArray, QByteArray> &info) m_d->addInfo(info); } +void MetaObjectBuilder::addEnumerator(const char *name, bool flag, bool scoped, + const QVector<QPair<QByteArray, int> > &entries) +{ + m_d->addEnumerator(name, flag, scoped, entries); +} + +void MetaObjectBuilderPrivate::addEnumerator(const char *name, bool flag, bool scoped, + const QVector<QPair<QByteArray, int> > &entries) +{ + auto builder = ensureBuilder(); + int have_already = builder->indexOfEnumerator(name); + if (have_already >= 0) + builder->removeEnumerator(have_already); + auto enumbuilder = builder->addEnumerator(name); + enumbuilder.setIsFlag(flag); + enumbuilder.setIsScoped(scoped); + + for (auto item : entries) + enumbuilder.addKey(item.first, item.second); + m_dirty = true; +} + void MetaObjectBuilderPrivate::removeProperty(int index) { index -= m_baseObject->propertyCount(); @@ -430,6 +457,8 @@ const QMetaObject *MetaObjectBuilder::update() return m_d->update(); } +using namespace Shiboken; + void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) { // Get all non-QObject-derived base types in method resolution order, filtering out the types @@ -439,7 +468,7 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) // existing connections. const PyObject *mro = type->tp_mro; const Py_ssize_t basesCount = PyTuple_GET_SIZE(mro); - PyTypeObject *qObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*"); + PyTypeObject *qObjectType = Conversions::getPythonTypeObject("QObject*"); std::vector<PyTypeObject *> basesToCheck; // Prepend the actual type that we are parsing. @@ -470,7 +499,7 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) // Register signals. auto data = reinterpret_cast<PySideSignal *>(value); if (data->data->signalName.isEmpty()) - data->data->signalName = Shiboken::String::toCString(key); + data->data->signalName = String::toCString(key); for (const auto &s : data->data->signatures) { const auto sig = data->data->signalName + '(' + s.signature + ')'; if (m_baseObject->indexOfSignal(sig) == -1) { @@ -489,7 +518,7 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) } } - Shiboken::AutoDecRef slotAttrName(Shiboken::String::fromCString(PYSIDE_SLOT_LIST_ATTR)); + AutoDecRef slotAttrName(String::fromCString(PYSIDE_SLOT_LIST_ATTR)); // PYSIDE-315: Now take care of the rest. // Signals and slots should be separated, unless the types are modified, later. // We check for this using "is_sorted()". Sorting no longer happens at all. @@ -501,16 +530,16 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) while (PyDict_Next(attrs, &pos, &key, &value)) { if (Property::checkType(value)) { - const int index = m_baseObject->indexOfProperty(Shiboken::String::toCString(key)); + const int index = m_baseObject->indexOfProperty(String::toCString(key)); if (index == -1) - addProperty(Shiboken::String::toCString(key), value); + addProperty(String::toCString(key), value); } else if (PyFunction_Check(value)) { // Register slots. if (PyObject_HasAttr(value, slotAttrName)) { PyObject *signatureList = PyObject_GetAttr(value, slotAttrName); for (Py_ssize_t i = 0, i_max = PyList_Size(signatureList); i < i_max; ++i) { PyObject *pySignature = PyList_GET_ITEM(signatureList, i); - QByteArray signature(Shiboken::String::toCString(pySignature)); + QByteArray signature(String::toCString(pySignature)); // Split the slot type and its signature. QByteArray type; const int spacePos = signature.indexOf(' '); @@ -530,4 +559,29 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) } } } + // PYSIDE-957: Collect the delayed QEnums + auto collectedEnums = PySide::QEnum::resolveDelayedQEnums(type); + for (PyObject *obEnumType : collectedEnums) { + bool isFlag = PySide::QEnum::isFlag(obEnumType); + AutoDecRef obName(PyObject_GetAttr(obEnumType, PyMagicName::name())); + // Everything has been checked already in resolveDelayedQEnums. + // Therefore, we don't need to error-check here again. + auto name = String::toCString(obName); + AutoDecRef members(PyObject_GetAttr(obEnumType, PyMagicName::members())); + AutoDecRef items(PepMapping_Items(members)); + Py_ssize_t nr_items = PySequence_Length(items); + + QVector<QPair<QByteArray, int> > entries; + for (Py_ssize_t idx = 0; idx < nr_items; ++idx) { + AutoDecRef item(PySequence_GetItem(items, idx)); + AutoDecRef key(PySequence_GetItem(item, 0)); + AutoDecRef member(PySequence_GetItem(item, 1)); + AutoDecRef value(PyObject_GetAttr(member, Shiboken::PyName::value())); + auto ckey = String::toCString(key); + auto ivalue = PyInt_AsSsize_t(value); // int/long cheating + auto thing = QPair<QByteArray, int>(ckey, int(ivalue)); + entries.push_back(thing); + } + addEnumerator(name, isFlag, true, entries); + } } diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.h b/sources/pyside2/libpyside/dynamicqmetaobject.h index 1fbe73ea4..7279d5c26 100644 --- a/sources/pyside2/libpyside/dynamicqmetaobject.h +++ b/sources/pyside2/libpyside/dynamicqmetaobject.h @@ -68,7 +68,10 @@ public: int addProperty(const char *property, PyObject *data); void addInfo(const char *key, const char *value); void addInfo(const QMap<QByteArray, QByteArray> &info); - + void addEnumerator(const char *name, + bool flag, + bool scoped, + const QVector<QPair<QByteArray, int> > &entries); void removeProperty(int index); const QMetaObject *update(); diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp index e2b8708ce..66e931164 100644 --- a/sources/pyside2/libpyside/pyside.cpp +++ b/sources/pyside2/libpyside/pyside.cpp @@ -50,7 +50,6 @@ #include "pysidemetafunction_p.h" #include "pysidemetafunction.h" #include "dynamicqmetaobject.h" -#include "destroylistener.h" #include <autodecref.h> #include <basewrapper.h> @@ -166,12 +165,10 @@ void registerCleanupFunction(CleanupFunction func) void runCleanupFunctions() { - //PySide::DestroyListener::instance()->destroy(); while (!cleanupFunctionList.isEmpty()) { CleanupFunction f = cleanupFunctionList.pop(); f(); } - PySide::DestroyListener::destroy(); } static void destructionVisitor(SbkObject *pyObj, void *data) @@ -226,8 +223,7 @@ std::size_t getSizeOfQObject(SbkObjectType *type) void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base, std::size_t cppObjSize) { //create DynamicMetaObject based on python type - auto userData = - new TypeUserData(reinterpret_cast<PyTypeObject *>(type), base, cppObjSize); + auto userData = new TypeUserData(reinterpret_cast<PyTypeObject *>(type), base, cppObjSize); userData->mo.update(); Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>); @@ -271,11 +267,6 @@ const QMetaObject *retrieveMetaObject(PyObject *pyObj) return retrieveMetaObject(pyTypeObj); } -void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base) -{ - initDynamicMetaObject(type, base, 0); -} - void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject * /* kwds */) { PyTypeObject *qObjType = Shiboken::Conversions::getPythonTypeObject("QObject*"); diff --git a/sources/pyside2/libpyside/pyside.h b/sources/pyside2/libpyside/pyside.h index ae400e1fe..95abaeeb1 100644 --- a/sources/pyside2/libpyside/pyside.h +++ b/sources/pyside2/libpyside/pyside.h @@ -99,7 +99,6 @@ template<typename T> struct initQtMetaType<T, false> { }; -PYSIDE_DEPRECATED(PYSIDE_API void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base)); PYSIDE_API void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base, std::size_t cppObjSize); PYSIDE_API void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject *kwds); diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp index 77dc6f3fc..e9548dc22 100644 --- a/sources/pyside2/libpyside/pysideproperty.cpp +++ b/sources/pyside2/libpyside/pysideproperty.cpp @@ -377,11 +377,6 @@ bool checkType(PyObject *pyObj) return false; } -bool isPropertyType(PyObject *pyObj) -{ - return checkType(pyObj); -} - int setValue(PySideProperty *self, PyObject *source, PyObject *value) { PyObject *fset = self->d->fset; diff --git a/sources/pyside2/libpyside/pysideproperty.h b/sources/pyside2/libpyside/pysideproperty.h index 0ea5e84d6..a97b2a48f 100644 --- a/sources/pyside2/libpyside/pysideproperty.h +++ b/sources/pyside2/libpyside/pysideproperty.h @@ -64,9 +64,6 @@ typedef void (*MetaCallHandler)(PySideProperty*,PyObject*,QMetaObject::Call, voi PYSIDE_API bool checkType(PyObject* pyObj); -/// @deprecated Use checkType -PYSIDE_DEPRECATED(PYSIDE_API bool isPropertyType(PyObject* pyObj)); - /** * This function call set property function and pass value as arg * This function does not check the property object type diff --git a/sources/pyside2/libpyside/pysideqenum.cpp b/sources/pyside2/libpyside/pysideqenum.cpp new file mode 100644 index 000000000..f46b5536c --- /dev/null +++ b/sources/pyside2/libpyside/pysideqenum.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <shiboken.h> + +#include "pysideqenum.h" +#include "dynamicqmetaobject.h" +#include "pyside_p.h" + + +/////////////////////////////////////////////////////////////// +// +// PYSIDE-957: Create QEnum dynamically from Python Enum +// +// +extern "C" { + +using namespace Shiboken; + +static PyObject *analyzePyEnum(PyObject *pyenum, PyObject *container = nullptr) +{ + /* + * This is the straight-forward implementation of QEnum/QFlag. It does no + * longer create an equivalent Qt enum but takes the Python enum as-is. + * + * It parses an Enum/Flag derived Python enum completely so that + * registering can be done without error checks. This would be impossible + * in MetaObjectBuilderPrivate::parsePythonType. + */ + AutoDecRef members(PyObject_GetAttr(pyenum, Shiboken::PyMagicName::members())); + if (members.isNull()) + return nullptr; + AutoDecRef items(PepMapping_Items(members)); + if (items.isNull()) + return nullptr; + int iflag = PySide::QEnum::isFlag(pyenum); + if (iflag < 0) + return nullptr; + Py_ssize_t nr_items = PySequence_Length(items); + if (nr_items < 0) + return nullptr; + + for (Py_ssize_t idx = 0; idx < nr_items; ++idx) { + AutoDecRef item(PySequence_GetItem(items, idx)); + if (item.isNull()) + return nullptr; + + // The item should be a 2-element sequence of the key name and an + // object containing the value. + AutoDecRef key(PySequence_GetItem(item, 0)); + AutoDecRef member(PySequence_GetItem(item, 1)); + if (key.isNull() || member.isNull()) + return nullptr; + if (!Shiboken::String::check(key)) { + // '%.200s' is the safety stringbuffer size of most CPython functions. + PyErr_Format(PyExc_TypeError, + "QEnum expected a string mapping as __members__, got '%.200s'", + Py_TYPE(key)->tp_name); + return nullptr; + } + + // Get the value. + AutoDecRef value(PyObject_GetAttr(member, Shiboken::PyName::value())); + if (value.isNull()) + return nullptr; + if (!PyInt_Check(value)) { // int/long cheating + PyErr_Format(PyExc_TypeError, + "QEnum expected an int value as '%.200s', got '%.200s'", + Shiboken::String::toCString(key), Py_TYPE(value)->tp_name); + return nullptr; + } + } + Py_RETURN_NONE; +} + +static Py_ssize_t get_lineno() +{ + PyObject *frame = reinterpret_cast<PyObject *>(PyEval_GetFrame()); // borrowed ref + AutoDecRef ob_lineno(PyObject_GetAttr(frame, Shiboken::PyName::f_lineno())); + if (ob_lineno.isNull() || !PyInt_Check(ob_lineno)) // int/long cheating + return -1; + return PyInt_AsSsize_t(ob_lineno); // int/long cheating +} + +static bool is_module_code() +{ + PyObject *frame = reinterpret_cast<PyObject *>(PyEval_GetFrame()); // borrowed ref + AutoDecRef ob_code(PyObject_GetAttr(frame, Shiboken::PyName::f_code())); + if (ob_code.isNull()) + return false; + AutoDecRef ob_name(PyObject_GetAttr(ob_code, Shiboken::PyName::co_name())); + if (ob_name.isNull()) + return false; + const char *codename = Shiboken::String::toCString(ob_name); + return strcmp(codename, "<module>") == 0; +} + +} // extern "C" + +namespace PySide { namespace QEnum { + +static std::map<int, PyObject *> enumCollector; + +int isFlag(PyObject *obType) +{ + /* + * Find out if this is an Enum or a Flag derived class. + * It checks also if things come from the enum module and if it is + * an Enum or Flag class at all. + * + * The function is called in MetaObjectBuilderPrivate::parsePythonType + * again to obtain the flag value. + */ + if (!PyType_Check(obType)) { + PyErr_Format(PyExc_TypeError, "a class argument was expected, not a '%.200s' instance", + Py_TYPE(obType)->tp_name); + return -1; + }; + auto *type = reinterpret_cast<PyTypeObject *>(obType); + PyObject *mro = type->tp_mro; + Py_ssize_t i, n = PyTuple_GET_SIZE(mro); + bool right_module = false; + bool have_enum = false; + bool have_flag = false; + bool have_members = PyObject_HasAttr(obType, PyMagicName::members()); + for (i = 0; i < n; i++) { + obType = PyTuple_GET_ITEM(mro, i); + type = reinterpret_cast<PyTypeObject *>(obType); + AutoDecRef mod(PyObject_GetAttr(obType, PyMagicName::module())); + QByteArray cmod = String::toCString(mod); + QByteArray cname = type->tp_name; + if (cmod == "enum") { + right_module = true; + if (cname == "Enum") + have_enum = true; + else if (cname == "Flag") + have_flag = true; + } + } + if (!right_module || !(have_enum || have_flag) || !have_members) { + PyErr_Format(PyExc_TypeError, "type %.200s does not inherit from 'Enum' or 'Flag'", + type->tp_name); + return -1; + } + return bool(have_flag); +} + +PyObject *QEnumMacro(PyObject *pyenum, bool flag) +{ + /* + * This is the official interface of 'QEnum'. It first calls 'analyzePyEnum'. + * When called as toplevel enum, it simply returns after some checks. + * Otherwise, 'pyenum' is stored for later use by the meta class registation. + */ + int computedFlag = isFlag(pyenum); + if (computedFlag < 0) + return nullptr; + if (bool(computedFlag) != flag) { + AutoDecRef name(PyObject_GetAttr(pyenum, PyMagicName::qualname())); + auto cname = String::toCString(name); + const char *e = "Enum"; + const char *f = "Flag"; + PyErr_Format(PyExc_TypeError, "expected '%s' but got '%s' (%.200s)", + flag ? f : e, flag ? e : f, cname); + return nullptr; + } + auto ok = analyzePyEnum(pyenum); + if (ok == nullptr) + return nullptr; + if (is_module_code()) { + // This is a toplevel enum which we resolve immediately. + Py_INCREF(pyenum); + return pyenum; + } + + Py_ssize_t lineno = get_lineno(); + if (lineno < 0) + return nullptr; + // Handle the rest via line number and the meta class. + Py_INCREF(pyenum); + Py_XDECREF(enumCollector[lineno]); + enumCollector[lineno] = pyenum; + Py_RETURN_NONE; +} + +std::vector<PyObject *> resolveDelayedQEnums(PyTypeObject *containerType) +{ + /* + * This is the internal interface of 'QEnum'. + * It is called at the end of the meta class call 'SbkObjectTypeTpNew' via + * MetaObjectBuilderPrivate::parsePythonType and resolves the collected + * Python Enum arguments. The result is then registered. + */ + if (enumCollector.empty()) + return {}; + PyObject *obContainerType = reinterpret_cast<PyObject *>(containerType); + Py_ssize_t lineno = get_lineno(); + + std::vector<PyObject *> result; + + auto it = enumCollector.begin(); + while (it != enumCollector.end()) { + int nr = it->first; + PyObject *pyenum = it->second; + if (nr >= lineno) { + AutoDecRef name(PyObject_GetAttr(pyenum, PyMagicName::name())); + if (name.isNull() || PyObject_SetAttr(obContainerType, name, pyenum) < 0) + return {}; + result.push_back(pyenum); + it = enumCollector.erase(it); + } else { + ++it; + } + } + return result; +} + +} // namespace Enum +} // namespace Shiboken + +// +/////////////////////////////////////////////////////////////// diff --git a/sources/pyside2/libpyside/destroylistener.h b/sources/pyside2/libpyside/pysideqenum.h index dedcca662..fc4e55982 100644 --- a/sources/pyside2/libpyside/destroylistener.h +++ b/sources/pyside2/libpyside/pysideqenum.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -37,36 +37,21 @@ ** ****************************************************************************/ -#ifndef PYSIDE_DESTROY_LISTENER -#define PYSIDE_DESTROY_LISTENER +#ifndef PYSIDE_QENUM_H +#define PYSIDE_QENUM_H -#include "pysidemacros.h" +#include <pysidemacros.h> +#include <vector> -#include <QtCore/QObject> +namespace PySide { namespace QEnum { -namespace PySide -{ -struct DestroyListenerPrivate; -/// \deprecated This class is deprecated and isn't used by libpyside anymore. -class PYSIDE_API DestroyListener : public QObject -{ - Q_OBJECT - public: - PYSIDE_DEPRECATED(static DestroyListener *instance()); - static void destroy(); - void listen(QObject *obj); +// PYSIDE-957: Support the QEnum macro +PYSIDE_API PyObject *QEnumMacro(PyObject *, bool); +PYSIDE_API int isFlag(PyObject *); +PYSIDE_API std::vector<PyObject *> resolveDelayedQEnums(PyTypeObject *); +PYSIDE_API void init(); - public Q_SLOTS: - void onObjectDestroyed(QObject *obj); - - private: - static DestroyListener *m_instance; - DestroyListenerPrivate *m_d; - DestroyListener(QObject *parent); - ~DestroyListener() override; -}; - -}//namespace +} // namespace QEnum +} // namespace PySide #endif - diff --git a/sources/pyside2/libpyside/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp index d7e6b4f4c..b141ce157 100644 --- a/sources/pyside2/libpyside/pysideqflags.cpp +++ b/sources/pyside2/libpyside/pysideqflags.cpp @@ -175,18 +175,18 @@ namespace QFlags // PYSIDE-747: Here we insert now the full class name. strcpy(qualname, name); // Careful: SbkType_FromSpec does not allocate the string. - PyType_Spec *newspec = new PyType_Spec; - newspec->name = strdup(qualname); - newspec->basicsize = SbkNewQFlagsType_spec.basicsize; - newspec->itemsize = SbkNewQFlagsType_spec.itemsize; - newspec->flags = SbkNewQFlagsType_spec.flags; + PyType_Spec newspec; + newspec.name = strdup(qualname); + newspec.basicsize = SbkNewQFlagsType_spec.basicsize; + newspec.itemsize = SbkNewQFlagsType_spec.itemsize; + newspec.flags = SbkNewQFlagsType_spec.flags; int idx = -1; while (numberMethods[++idx].slot) { assert(SbkNewQFlagsType_slots[idx].slot == numberMethods[idx].slot); SbkNewQFlagsType_slots[idx].pfunc = numberMethods[idx].pfunc; } - newspec->slots = SbkNewQFlagsType_spec.slots; - PyTypeObject *type = (PyTypeObject *)SbkType_FromSpec(newspec); + newspec.slots = SbkNewQFlagsType_spec.slots; + PyTypeObject *type = (PyTypeObject *)SbkType_FromSpec(&newspec); Py_TYPE(type) = &PyType_Type; PySideQFlagsType *flagsType = reinterpret_cast<PySideQFlagsType *>(type); diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp index 0fa33254c..32e1bb0c6 100644 --- a/sources/pyside2/libpyside/pysidesignal.cpp +++ b/sources/pyside2/libpyside/pysidesignal.cpp @@ -54,7 +54,6 @@ #include <utility> #define QT_SIGNAL_SENTINEL '2' -#define PyEnumMeta_Check(x) (strcmp(Py_TYPE(arg)->tp_name, "EnumMeta") == 0) namespace PySide { namespace Signal { @@ -805,32 +804,6 @@ PySideSignalInstance *newObjectFromMethod(PyObject *source, const QList<QMetaMet return root; } -PySideSignal *newObject(const char *name, ...) -{ - va_list listSignatures; - char *sig = nullptr; - PySideSignal *self = PyObject_New(PySideSignal, PySideSignalTypeF()); - self->data = new PySideSignalData; - self->data->signalName = name; - self->homonymousMethod = 0; - - va_start(listSignatures, name); - sig = va_arg(listSignatures, char *); - - while (sig != NULL) { - if (strcmp(sig, "void") == 0) - appendSignature(self, SignalSignature("")); - else - appendSignature(self, SignalSignature(sig)); - - sig = va_arg(listSignatures, char *); - } - - va_end(listSignatures); - - return self; -} - template<typename T> static typename T::value_type join(T t, const char *sep) { @@ -914,11 +887,6 @@ PyObject *buildQtCompatible(const QByteArray &signature) return Shiboken::String::fromStringAndSize(ba, ba.size()); } -void addSignalToWrapper(SbkObjectType *wrapperType, const char *signalName, PySideSignal *signal) -{ - _addSignalToWrapper(wrapperType, signalName, signal); -} - PyObject *getObject(PySideSignalInstance *signal) { return signal->d->source; diff --git a/sources/pyside2/libpyside/pysidesignal.h b/sources/pyside2/libpyside/pysidesignal.h index a2d58a27c..a6742227f 100644 --- a/sources/pyside2/libpyside/pysidesignal.h +++ b/sources/pyside2/libpyside/pysidesignal.h @@ -75,16 +75,6 @@ namespace Signal { PYSIDE_API bool checkType(PyObject* type); /** - * This function creates a Signal object which stays attached to QObject class - * - * @param name of the Signal to be registered on meta object - * @param signatures a list of signatures supported by this signal, ended with a NULL pointer - * @return Return a new reference to PyObject* of type PySideSignal - * @deprecated Use registerSignals - **/ -PYSIDE_DEPRECATED(PYSIDE_API PySideSignal* newObject(const char* name, ...)); - -/** * Register all C++ signals of a QObject on Python type. */ PYSIDE_API void registerSignals(SbkObjectType* pyObj, const QMetaObject* metaObject); @@ -133,11 +123,6 @@ PYSIDE_API const char* getSignature(PySideSignalInstance* signal); PYSIDE_API void updateSourceObject(PyObject* source); /** - * @deprecated Use registerSignals - **/ -PYSIDE_DEPRECATED(PYSIDE_API void addSignalToWrapper(SbkObjectType* wrapperType, const char* signalName, PySideSignal* signal)); - -/** * This function verifies if the signature is a QtSignal base on SIGNAL flag * @param signature The signal signature * @return Return true if this is a Qt Signal, otherwise return false diff --git a/sources/pyside2/plugins/CMakeLists.txt b/sources/pyside2/plugins/CMakeLists.txt index f39575542..c9e652800 100644 --- a/sources/pyside2/plugins/CMakeLists.txt +++ b/sources/pyside2/plugins/CMakeLists.txt @@ -9,21 +9,28 @@ set(ui_plugin_moc customwidget.h customwidgets.h ) -include_directories(${Qt5Designer_INCLUDE_DIRS}) +include_directories(${Qt${QT_MAJOR_VERSION}Designer_INCLUDE_DIRS}) + +if (${QT_MAJOR_VERSION} GREATER_EQUAL 6) + qt6_wrap_cpp(MOC_FILES ${ui_plugin_moc}) +else() + qt5_wrap_cpp(MOC_FILES ${ui_plugin_moc}) +endif() -qt5_wrap_cpp(MOC_FILES ${ui_plugin_moc}) add_library(uiplugin STATIC ${ui_plugin_src} ${MOC_FILES}) if(CMAKE_HOST_UNIX AND NOT CYGWIN) add_definitions(-fPIC) endif() add_definitions(-DQT_STATICPLUGIN) -if(Qt5Core_VERSION VERSION_GREATER "5.7.1") - set_property(TARGET uiplugin PROPERTY CXX_STANDARD 11) +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + set_property(TARGET pyside2 PROPERTY CXX_STANDARD 17) +else() + set_property(TARGET pyside2 PROPERTY CXX_STANDARD 11) endif() target_link_libraries(uiplugin - ${Qt5UiTools_LIBRARY} + ${Qt${QT_MAJOR_VERSION}UiTools_LIBRARY} Shiboken2::libshiboken) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/sources/pyside2/pyside_version.py b/sources/pyside2/pyside_version.py index 0e0943143..f5ef03613 100644 --- a/sources/pyside2/pyside_version.py +++ b/sources/pyside2/pyside_version.py @@ -38,13 +38,13 @@ ############################################################################# major_version = "5" -minor_version = "14" -patch_version = "2" +minor_version = "15" +patch_version = "0" # For example: "a", "b", "rc" # (which means "alpha", "beta", "release candidate"). # An empty string means the generated package will be an official release. -pre_release_version_type = "a" +release_version_type = "a" # For example: "1", "2" (which means "beta1", "beta2", if type is "b"). pre_release_version = "1" @@ -52,4 +52,4 @@ pre_release_version = "1" if __name__ == '__main__': # Used by CMake. print('{0};{1};{2};{3};{4}'.format(major_version, minor_version, patch_version, - pre_release_version_type, pre_release_version)) + release_version_type, pre_release_version)) diff --git a/sources/pyside2/tests/CMakeLists.txt b/sources/pyside2/tests/CMakeLists.txt index 60179d81f..285ea872f 100644 --- a/sources/pyside2/tests/CMakeLists.txt +++ b/sources/pyside2/tests/CMakeLists.txt @@ -46,7 +46,7 @@ else() foreach(shortname IN LISTS all_module_shortnames) message(STATUS "preparing tests for module 'Qt${shortname}'") - TEST_QT_MODULE(Qt5${shortname}_FOUND Qt${shortname}) + TEST_QT_MODULE(Qt${QT_MAJOR_VERSION}${shortname}_FOUND Qt${shortname}) endforeach() #platform specific diff --git a/sources/pyside2/tests/QtCore/CMakeLists.txt b/sources/pyside2/tests/QtCore/CMakeLists.txt index 35e42e2ae..a151e6d11 100644 --- a/sources/pyside2/tests/QtCore/CMakeLists.txt +++ b/sources/pyside2/tests/QtCore/CMakeLists.txt @@ -52,7 +52,8 @@ PYSIDE_TEST(qbytearray_concatenation_operator_test.py) PYSIDE_TEST(qbytearray_operator_iadd_test.py) PYSIDE_TEST(qbytearray_operator_test.py) PYSIDE_TEST(qbytearray_test.py) -if (Qt5Core_VERSION VERSION_EQUAL 5.14.0 OR Qt5Core_VERSION VERSION_GREATER 5.14.0) +if (Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_EQUAL 5.14.0 + OR Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_GREATER 5.14.0) PYSIDE_TEST(qcalendar_test.py) endif() PYSIDE_TEST(qcbor_test.py) diff --git a/sources/pyside2/tests/QtCore/qenum_test.py b/sources/pyside2/tests/QtCore/qenum_test.py index 1edb8981a..f99a893d9 100644 --- a/sources/pyside2/tests/QtCore/qenum_test.py +++ b/sources/pyside2/tests/QtCore/qenum_test.py @@ -2,7 +2,7 @@ ############################################################################# ## -## Copyright (C) 2016 The Qt Company Ltd. +## Copyright (C) 2020 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of the test suite of Qt for Python. @@ -40,7 +40,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from init_paths import init_test_paths init_test_paths(False) -from PySide2.QtCore import Qt, QIODevice +from PySide2.QtCore import Qt, QIODevice, QObject, QEnum, QFlag class TestEnum(unittest.TestCase): @@ -68,28 +68,30 @@ class TestEnum(unittest.TestCase): # Floats with self.assertRaises(TypeError): - a = k+2.0 + a = k + 2.0 with self.assertRaises(TypeError): - a = k-2.0 + a = k - 2.0 with self.assertRaises(TypeError): - a = k*2.0 + a = k * 2.0 - @unittest.skipUnless(getattr(sys, "getobjects", None), "requires debug build") + @unittest.skipUnless(getattr(sys, "getobjects", None), "requires --with-trace-refs") + @unittest.skipUnless(getattr(sys, "gettotalrefcount", None), "requires --with-pydebug") def testEnumNew_NoLeak(self): gc.collect() total = sys.gettotalrefcount() for idx in range(1000): ret = Qt.Key(42) + gc.collect() delta = sys.gettotalrefcount() - total print("delta total refcount =", delta) if abs(delta) >= 10: - all = sys.getobjects(0) - all.sort(key=lambda x: sys.getrefcount(x), reverse=True) + all = [(sys.getrefcount(x), x) for x in sys.getobjects(0)] + all.sort(key=lambda x: x[0], reverse=True) for ob in all[:10]: - print(sys.getrefcount(ob), ob) + print(ob) self.assertTrue(abs(delta) < 10) @@ -141,6 +143,105 @@ class TestEnumPickling(unittest.TestCase): else: func() +# PYSIDE-957: The QEnum macro + +try: + import enum + HAVE_ENUM = True +except ImportError: + HAVE_ENUM = False + QEnum = QFlag = lambda x: x + import types + class Enum: pass + enum = types.ModuleType("enum") + enum.Enum = enum.Flag = enum.IntEnum = enum.IntFlag = Enum + Enum.__module__ = "enum" + Enum.__members__ = {} + del Enum + enum.auto = lambda: 42 + +HAVE_FLAG = hasattr(enum, "Flag") + +@QEnum +class OuterEnum(enum.Enum): + A = 1 + B = 2 + +class SomeClass(QObject): + + @QEnum + class SomeEnum(enum.Enum): + A = 1 + B = 2 + C = 3 + + @QEnum + class OtherEnum(enum.IntEnum): + A = 1 + B = 2 + C = 3 + + class InnerClass(QObject): + + @QEnum + class InnerEnum(enum.Enum): + X = 42 + + class SomeEnum(enum.Enum): + A = 4 + B = 5 + C = 6 + + QEnum(SomeEnum) # works even without the decorator assignment + + +@unittest.skipUnless(HAVE_ENUM, "requires 'enum' module (use 'pip install enum34' for Python 2)") +class TestQEnumMacro(unittest.TestCase): + def testTopLevel(self): + self.assertEqual(type(OuterEnum).__module__, "enum") + self.assertEqual(type(OuterEnum).__name__, "EnumMeta") + self.assertEqual(len(OuterEnum.__members__), 2) + + def testSomeClass(self): + self.assertEqual(type(SomeClass.SomeEnum).__module__, "enum") + self.assertEqual(type(SomeClass.SomeEnum).__name__, "EnumMeta") + self.assertEqual(len(SomeClass.SomeEnum.__members__), 3) + with self.assertRaises(TypeError): + int(SomeClass.SomeEnum.C) == 6 + self.assertEqual(SomeClass.OtherEnum.C, 3) + + @unittest.skipIf(sys.version_info[0] < 3, "we cannot support nested classes in Python 2") + def testInnerClass(self): + self.assertEqual(SomeClass.InnerClass.InnerEnum.__qualname__, + "SomeClass.InnerClass.InnerEnum") + with self.assertRaises(TypeError): + int(SomeClass.InnerClass.InnerEnum.X) == 42 + + @unittest.skipUnless(HAVE_FLAG, "some older Python versions have no 'Flag'") + def testEnumFlag(self): + with self.assertRaises(TypeError): + class WrongFlagForEnum(QObject): + @QEnum + class Bad(enum.Flag): + pass + with self.assertRaises(TypeError): + class WrongEnuForFlag(QObject): + @QFlag + class Bad(enum.Enum): + pass + + def testIsRegistered(self): + mo = SomeClass.staticMetaObject + self.assertEqual(mo.enumeratorCount(), 2) + self.assertEqual(mo.enumerator(0).name(), "OtherEnum") + self.assertEqual(mo.enumerator(0).scope(), "SomeClass") + self.assertEqual(mo.enumerator(1).name(), "SomeEnum") + moi = SomeClass.InnerClass.staticMetaObject + self.assertEqual(moi.enumerator(0).name(), "InnerEnum") + ## Question: Should that scope not better be "SomeClass.InnerClass"? + ## But we have __qualname__ already: + self.assertEqual(moi.enumerator(0).scope(), "InnerClass") + if __name__ == '__main__': unittest.main() diff --git a/sources/pyside2/tests/QtNetwork/CMakeLists.txt b/sources/pyside2/tests/QtNetwork/CMakeLists.txt index 57c5266c8..754f8e5af 100644 --- a/sources/pyside2/tests/QtNetwork/CMakeLists.txt +++ b/sources/pyside2/tests/QtNetwork/CMakeLists.txt @@ -2,7 +2,7 @@ PYSIDE_TEST(bug_446.py) PYSIDE_TEST(bug_1084.py) PYSIDE_TEST(accessManager_test.py) PYSIDE_TEST(dnslookup_test.py) -# Qt5: QHttp is gone PYSIDE_TEST(http_test.py) +# Qt${QT_MAJOR_VERSION}: QHttp is gone PYSIDE_TEST(http_test.py) PYSIDE_TEST(qpassworddigestor_test.py) PYSIDE_TEST(tcpserver_test.py) PYSIDE_TEST(udpsocket_test.py) diff --git a/sources/pyside2/tests/QtQuickControls2/CMakeLists.txt b/sources/pyside2/tests/QtQuickControls2/CMakeLists.txt new file mode 100644 index 000000000..2f7cb08b9 --- /dev/null +++ b/sources/pyside2/tests/QtQuickControls2/CMakeLists.txt @@ -0,0 +1 @@ +# Please add some tests, here diff --git a/sources/pyside2/tests/QtSerialPort/CMakeLists.txt b/sources/pyside2/tests/QtSerialPort/CMakeLists.txt new file mode 100644 index 000000000..554373445 --- /dev/null +++ b/sources/pyside2/tests/QtSerialPort/CMakeLists.txt @@ -0,0 +1 @@ +PYSIDE_TEST(serial.py) diff --git a/sources/pyside2/tests/QtSerialPort/serial.py b/sources/pyside2/tests/QtSerialPort/serial.py new file mode 100644 index 000000000..7c0839d8e --- /dev/null +++ b/sources/pyside2/tests/QtSerialPort/serial.py @@ -0,0 +1,95 @@ +#!/usr/bin/python + +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for QSerialPort''' + +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from init_paths import init_test_paths +init_test_paths(False) + +from PySide2.QtSerialPort import QSerialPort, QSerialPortInfo +from PySide2.QtCore import QIODevice + +class QSerialPortTest(unittest.TestCase): + def testDefaultConstructedPort(self): + serialPort = QSerialPort() + + self.assertEqual(serialPort.error(), QSerialPort.NoError) + self.assertTrue(not serialPort.errorString() == "") + + # properties + defaultBaudRate = QSerialPort.Baud9600 + self.assertEqual(serialPort.baudRate(), defaultBaudRate) + self.assertEqual(serialPort.baudRate(QSerialPort.Input), defaultBaudRate) + self.assertEqual(serialPort.baudRate(QSerialPort.Output), defaultBaudRate) + self.assertEqual(serialPort.dataBits(), QSerialPort.Data8) + self.assertEqual(serialPort.parity(), QSerialPort.NoParity) + self.assertEqual(serialPort.stopBits(), QSerialPort.OneStop) + self.assertEqual(serialPort.flowControl(), QSerialPort.NoFlowControl) + + self.assertEqual(serialPort.pinoutSignals(), QSerialPort.NoSignal) + self.assertEqual(serialPort.isRequestToSend(), False) + self.assertEqual(serialPort.isDataTerminalReady(), False) + + # QIODevice + self.assertEqual(serialPort.openMode(), QIODevice.NotOpen) + self.assertTrue(not serialPort.isOpen()) + self.assertTrue(not serialPort.isReadable()) + self.assertTrue(not serialPort.isWritable()) + self.assertTrue(serialPort.isSequential()) + self.assertEqual(serialPort.canReadLine(), False) + self.assertEqual(serialPort.pos(), 0) + self.assertEqual(serialPort.size(), 0) + self.assertTrue(serialPort.atEnd()) + self.assertEqual(serialPort.bytesAvailable(), 0) + self.assertEqual(serialPort.bytesToWrite(), 0) + + def testOpenExisting(self): + allportinfos = QSerialPortInfo.availablePorts() + for portinfo in allportinfos: + serialPort = QSerialPort(portinfo) + self.assertEqual(serialPort.portName(), portinfo.portName()) + + +class QSerialPortInfoTest(unittest.TestCase): + def test_available_ports(self): + allportinfos = QSerialPortInfo.availablePorts() + for portinfo in allportinfos: + portinfo.description() + portinfo.hasProductIdentifier() + portinfo.hasVendorIdentifier() + portinfo.isNull() + +if __name__ == '__main__': + unittest.main() diff --git a/sources/pyside2/tests/pysidetest/CMakeLists.txt b/sources/pyside2/tests/pysidetest/CMakeLists.txt index 46a8023c3..bdd88ea37 100644 --- a/sources/pyside2/tests/pysidetest/CMakeLists.txt +++ b/sources/pyside2/tests/pysidetest/CMakeLists.txt @@ -5,11 +5,11 @@ cmake_minimum_required(VERSION 3.1) set(QT_USE_QTCORE 1) # no more supported: include(${QT_USE_FILE}) -add_definitions(${Qt5Core_DEFINITIONS}) +add_definitions(${Qt${QT_MAJOR_VERSION}Core_DEFINITIONS}) add_definitions(-DQT_SHARED) add_definitions(-DRXX_ALLOCATOR_INIT_0) -find_package(Qt5Widgets) +find_package(Qt${QT_MAJOR_VERSION}Widgets) set(pysidetest_SRC testobject.cpp @@ -23,7 +23,11 @@ testview.h hiddenobject.h ) -qt5_wrap_cpp(pysidetest_MOC_SRC ${pysidetest_MOC_HEADERS}) +if (${QT_MAJOR_VERSION} GREATER_EQUAL 6) + qt6_wrap_cpp(pysidetest_MOC_SRC ${pysidetest_MOC_HEADERS}) +else() + qt5_wrap_cpp(pysidetest_MOC_SRC ${pysidetest_MOC_HEADERS}) +endif() set(testbinding_SRC ${CMAKE_CURRENT_BINARY_DIR}/testbinding/testobject_wrapper.cpp @@ -43,9 +47,15 @@ ${CMAKE_CURRENT_BINARY_DIR}/testbinding/testbinding_module_wrapper.cpp # ./qt/lib/QtCore.framework; ./qt/lib/QtCore.framework/Headers ; ./qt/mkspecs/macx-clang # Thus we use the second direct path, which contains the actual header files. -list(GET Qt5Core_INCLUDE_DIRS 1 Qt5Core_DIRECT_INCLUDE_DIR) -list(GET Qt5Gui_INCLUDE_DIRS 1 Qt5Gui_DIRECT_INCLUDE_DIR) -list(GET Qt5Widgets_INCLUDE_DIRS 1 Qt5Widgets_DIRECT_INCLUDE_DIR) +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + set(Qt6Core_DIRECT_INCLUDE_DIR Qt6Core_INCLUDE_DIRS) + set(Qt6Gui_DIRECT_INCLUDE_DIR Qt6Gui_INCLUDE_DIRS) + set(Qt6Widgets_DIRECT_INCLUDE_DIR Qt6Widgets_INCLUDE_DIRS) +else() + list(GET Qt5Core_INCLUDE_DIRS 1 Qt5Core_DIRECT_INCLUDE_DIR) + list(GET Qt5Gui_INCLUDE_DIRS 1 Qt5Gui_DIRECT_INCLUDE_DIR) + list(GET Qt5Widgets_INCLUDE_DIRS 1 Qt5Widgets_DIRECT_INCLUDE_DIR) +endif() # Adjust include headers paths for frameworks. set(shiboken_framework_include_dirs_option "") @@ -59,9 +69,9 @@ make_path(testbinding_include_dirs ${pyside2_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../PySide2 ${CMAKE_CURRENT_SOURCE_DIR}/../../libpyside ${QT_INCLUDE_DIR} - ${Qt5Core_DIRECT_INCLUDE_DIR} - ${Qt5Gui_DIRECT_INCLUDE_DIR} - ${Qt5Widgets_DIRECT_INCLUDE_DIR} + ${Qt${QT_MAJOR_VERSION}Core_DIRECT_INCLUDE_DIR} + ${Qt${QT_MAJOR_VERSION}Gui_DIRECT_INCLUDE_DIR} + ${Qt${QT_MAJOR_VERSION}Widgets_DIRECT_INCLUDE_DIR} ) make_path(testbinding_typesystem_path ${pyside2_SOURCE_DIR} @@ -84,9 +94,9 @@ COMMENT "Running generator for test binding..." include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} + ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS} ${pyside2_SOURCE_DIR} ${QtCore_GEN_DIR} ${QtGui_GEN_DIR} @@ -96,9 +106,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} add_library(pysidetest SHARED ${pysidetest_SRC} ${pysidetest_MOC_SRC}) target_link_libraries(pysidetest Shiboken2::libshiboken - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES} ) add_library(testbinding MODULE ${testbinding_SRC}) @@ -119,9 +129,9 @@ target_link_libraries(testbinding pyside2 ${TESTBINDING_PYTHON_LIBS} Shiboken2::libshiboken - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Widgets_LIBRARIES}) + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Widgets_LIBRARIES}) add_dependencies(testbinding pyside2 QtCore QtGui QtWidgets pysidetest) create_generator_target(testbinding) @@ -129,7 +139,7 @@ create_generator_target(testbinding) PYSIDE_TEST(constructor_properties_test.py) PYSIDE_TEST(decoratedslot_test.py) # Will always crash when built against Qt 5.6, no point in running it. -if (Qt5Core_VERSION VERSION_GREATER 5.7.0) +if (Qt${QT_MAJOR_VERSION}Core_VERSION VERSION_GREATER 5.7.0) PYSIDE_TEST(delegatecreateseditor_test.py) endif() PYSIDE_TEST(all_modules_load_test.py) diff --git a/sources/pyside2/tests/registry/init_platform.py b/sources/pyside2/tests/registry/init_platform.py index a690a3120..e80c3b69f 100644 --- a/sources/pyside2/tests/registry/init_platform.py +++ b/sources/pyside2/tests/registry/init_platform.py @@ -141,8 +141,8 @@ Shiboken.__name__ = "Shiboken" sys.modules["Shiboken"] = sys.modules.pop("shiboken2") all_modules.append("Shiboken") -# 'sample' seems to be needed by 'other', so import it first. -for modname in "minimal sample other smart".split(): +# 'sample/smart' are needed by 'other', so import them first. +for modname in "minimal sample smart other".split(): sys.path.insert(0, os.path.join(shiboken_build_dir, "tests", modname + "binding")) __import__(modname) all_modules.append(modname) diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt index 4232fef66..f8e504583 100644 --- a/sources/shiboken2/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -30,8 +30,8 @@ parser/enumvalue.cpp xmlutils.cpp ) -find_package(Qt5XmlPatterns 5.12) -find_package(Qt5Xml 5.12) +find_package(Qt${QT_MAJOR_VERSION}XmlPatterns 5.12) +find_package(Qt${QT_MAJOR_VERSION}Xml 5.12) find_package(LibXml2 2.6.32) find_package(LibXslt 1.1.19) @@ -40,7 +40,7 @@ if (LIBXSLT_FOUND AND LIBXML2_FOUND) set(HAS_LIBXSLT 1) endif() -if(NOT Qt5XmlPatterns_FOUND AND NOT HAS_LIBXSLT) +if(NOT Qt${QT_MAJOR_VERSION}XmlPatterns_FOUND AND NOT HAS_LIBXSLT) set(DISABLE_DOCSTRINGS TRUE) message(WARNING "Documentation will not be built due to missing dependency (no Qt5XmlPatterns found).") @@ -54,7 +54,7 @@ target_include_directories(apiextractor PRIVATE ${CLANG_EXTRA_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/parser) -target_link_libraries(apiextractor PUBLIC Qt5::Core) +target_link_libraries(apiextractor PUBLIC Qt${QT_MAJOR_VERSION}::Core) target_link_libraries(apiextractor PRIVATE ${CLANG_EXTRA_LIBRARIES}) if (HAS_LIBXSLT) @@ -66,10 +66,10 @@ if (HAS_LIBXSLT) PRIVATE ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) endif() -if (Qt5XmlPatterns_FOUND) +if (Qt${QT_MAJOR_VERSION}XmlPatterns_FOUND) target_compile_definitions(apiextractor PUBLIC HAVE_QTXMLPATTERNS) target_sources(apiextractor PRIVATE xmlutils_qt.cpp) - target_link_libraries(apiextractor PUBLIC Qt5::Xml Qt5::XmlPatterns) + target_link_libraries(apiextractor PUBLIC Qt${QT_MAJOR_VERSION}::Xml Qt${QT_MAJOR_VERSION}::XmlPatterns) endif() if (NOT DISABLE_DOCSTRINGS) @@ -87,7 +87,7 @@ target_compile_definitions(apiextractor PRIVATE CMAKE_CXX_COMPILER="${CMAKE_CXX_ set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) if (BUILD_TESTS) - find_package(Qt5Test 5.12 REQUIRED) + find_package(Qt${QT_MAJOR_VERSION}Test 5.12 REQUIRED) set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) enable_testing() add_subdirectory(tests) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 8468cf858..dedf0db50 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -270,7 +270,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI const ArgumentModelItem &arg = arguments.at(1); if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) { if (arg->type().indirections() < 2) - cls->setToStringCapability(true, arg->type().indirections()); + cls->setToStringCapability(true, int(arg->type().indirections())); } } } @@ -410,6 +410,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments, unsigned clangFlags) { clang::Builder builder; + builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes()); if (level == LanguageLevel::Default) level = clang::emulatedCompilerLanguageLevel(); arguments.prepend(QByteArrayLiteral("-std=") @@ -512,7 +513,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) ReportHandler::startProgress("Fixing class inheritance..."); for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { - if (!cls->isInterface() && !cls->isNamespace()) { + if (!cls->isNamespace()) { setupInheritance(cls); if (!cls->hasVirtualDestructor() && cls->baseClass() && cls->baseClass()->hasVirtualDestructor()) @@ -530,7 +531,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) .arg(cls->name()); } else { const bool couldAddDefaultCtors = cls->isConstructible() - && !cls->isInterface() && !cls->isNamespace() + && !cls->isNamespace() && (cls->attributes() & AbstractMetaAttributes::HasRejectedConstructor) == 0; if (couldAddDefaultCtors) { if (!cls->hasConstructors()) @@ -549,11 +550,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) - && !entry->isString() - && !entry->isChar() && !entry->isContainer() && !entry->isCustom() - && !entry->isVariant() && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken).noquote().nospace() @@ -729,12 +727,6 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, m_smartPointers << cls; } else { m_metaClasses << cls; - if (cls->typeEntry()->designatedInterface()) { - AbstractMetaClass *interface = cls->extractInterface(); - m_metaClasses << interface; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name()); - } } } @@ -758,6 +750,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel return nullptr; } + if (namespaceItem->type() == NamespaceType::Inline) { + type->setInlineNamespace(true); + TypeDatabase::instance()->addInlineNamespaceLookups(type); + } + // Continue populating namespace? AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); if (!metaClass) { @@ -778,11 +775,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel m_itemToClass.insert(namespaceItem.data(), metaClass); } - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name()); - } - traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); pushScope(namespaceItem); @@ -911,9 +903,6 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & break; } - if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName(); - const EnumeratorList &enums = enumItem->enumerators(); for (const EnumeratorModelItem &value : enums) { @@ -924,11 +913,6 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & metaEnumValue->setStringValue(value->stringValue()); metaEnumValue->setValue(value->value()); metaEnum->addEnumValue(metaEnumValue); - - if (ReportHandler::isDebug(ReportHandler::FullDebug)) { - qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = " - << metaEnumValue->value() << " = " << metaEnumValue->value(); - } } m_enums.insert(typeEntry, metaEnum); @@ -1069,11 +1053,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem if (type->stream()) metaClass->setStream(true); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { const QString message = type->isContainer() ? QStringLiteral("container: '%1'").arg(fullClassName) : QStringLiteral("class: '%1'").arg(metaClass->fullName()); - qCDebug(lcShiboken) << message; + qCInfo(lcShiboken, "%s", qPrintable(message)); } TemplateParameterList template_parameters = classItem->templateParameters(); @@ -1215,7 +1199,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel metaField->setType(metaType); - AbstractMetaAttributes::Attributes attr = nullptr; + AbstractMetaAttributes::Attributes attr; if (field->isStatic()) attr |= AbstractMetaAttributes::Static; @@ -1288,7 +1272,7 @@ AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const Sco AbstractMetaClass::Attributes *constructorAttributes, AbstractMetaClass *currentClass) { - *constructorAttributes = nullptr; + *constructorAttributes = {}; AbstractMetaFunctionList result; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); @@ -1429,8 +1413,6 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) { - Q_ASSERT(!metaClass->isInterface()); - if (m_setupInheritanceDone.contains(metaClass)) return true; @@ -1470,61 +1452,23 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) TypeDatabase* types = TypeDatabase::instance(); - int primary = -1; - int primaries = 0; - for (int i = 0; i < baseClasses.size(); ++i) { - - if (types->isClassRejected(baseClasses.at(i))) - continue; - - TypeEntry* baseClassEntry = types->findType(baseClasses.at(i)); - if (!baseClassEntry) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' inherits from unknown base class '%2'") - .arg(metaClass->name(), baseClasses.at(i)); - } else if (!baseClassEntry->designatedInterface()) { // true for primary base class - primaries++; - primary = i; - } - } - - if (primary >= 0) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary)); - if (!baseClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown baseclass for '%1': '%2'") - .arg(metaClass->name(), baseClasses.at(primary)); - return false; - } - metaClass->setBaseClass(baseClass); - } - - for (int i = 0; i < baseClasses.size(); ++i) { - if (types->isClassRejected(baseClasses.at(i))) - continue; - - if (i != primary) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i)); - if (!baseClass) { + for (const auto &baseClassName : baseClasses) { + if (!types->isClassRejected(baseClassName)) { + if (!types->findType(baseClassName)) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i)); + << QStringLiteral("class '%1' inherits from unknown base class '%2'") + .arg(metaClass->name(), baseClassName); return false; } - - setupInheritance(baseClass); - - QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name(); - AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName); - if (!iface) { + auto baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClassName); + if (!baseClass) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName); + << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClassName); return false; } - metaClass->addInterface(iface); + metaClass->addBaseClass(baseClass); - const AbstractMetaClassList &interfaces = iface->interfaces(); - for (AbstractMetaClass* iface : interfaces) - metaClass->addInterface(iface); + setupInheritance(baseClass); } } @@ -1669,7 +1613,12 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); } } else { - metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); + auto type = AbstractMetaFunction::NormalFunction; + if (metaFunction->name() == QLatin1String("__getattro__")) + type = AbstractMetaFunction::GetAttroFunction; + else if (metaFunction->name() == QLatin1String("__setattro__")) + type = AbstractMetaFunction::SetAttroFunction; + metaFunction->setFunctionType(type); } metaFunction->setDeclaringClass(metaClass); @@ -1801,11 +1750,14 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio const QString &signature = functionSignature(functionItem); const bool rejected = TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason); - qCDebug(lcShiboken).nospace().noquote() << __FUNCTION__ - << ": Checking rejection for signature \"" << signature << "\" for " << className - << ": " << rejected; - if (rejected) + + if (rejected) { + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) { + qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).", + qPrintable(className), qPrintable(signature), qPrintable(rejectReason)); + } return nullptr; + } if (functionItem->isFriend()) return nullptr; @@ -1826,9 +1778,6 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio metaFunction->setConstant(functionItem->isConstant()); metaFunction->setExceptionSpecification(functionItem->exceptionSpecification()); - if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()"; - metaFunction->setName(functionName); metaFunction->setOriginalName(functionItem->name()); @@ -2071,6 +2020,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction: return nullptr; } + // These are only implicit and should not appear in code... auto *metaType = new AbstractMetaType; metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); @@ -2104,6 +2054,52 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC return type; } +// Helper for translateTypeStatic() +TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, + const QString &name, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d) +{ + // 5.1 - Try first using the current scope + if (currentClass) { + if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName)) + return {type}; + + // 5.1.1 - Try using the class parents' scopes + if (d && !currentClass->baseClassNames().isEmpty()) { + const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); + for (const AbstractMetaClass *cls : baseClasses) { + if (auto type = findTypeEntryUsingContext(cls, qualifiedName)) + return {type}; + } + } + } + + // 5.2 - Try without scope + auto types = TypeDatabase::instance()->findCppTypes(qualifiedName); + if (!types.isEmpty()) + return types; + + // 6. No? Try looking it up as a flags type + if (auto type = TypeDatabase::instance()->findFlagsType(qualifiedName)) + return {type}; + + // 7. No? Try looking it up as a container type + if (auto type = TypeDatabase::instance()->findContainerType(name)) + return {type}; + + // 8. No? Check if the current class is a template and this type is one + // of the parameters. + if (currentClass) { + const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); + for (TypeEntry *te : template_args) { + if (te->name() == qualifiedName) + return {te}; + } + } + return {}; +} + AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass, TranslateTypeFlags flags, @@ -2112,6 +2108,12 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ return translateTypeStatic(_typei, currentClass, this, flags, errorMessage); } +static bool isNumber(const QString &s) +{ + return std::all_of(s.cbegin(), s.cend(), + [](QChar c) { return c.isDigit(); }); +} + AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, AbstractMetaClass *currentClass, AbstractMetaBuilderPrivate *d, @@ -2236,47 +2238,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo typeInfo.clearInstantiations(); } - const TypeEntry *type = nullptr; - // 5. Try to find the type - - // 5.1 - Try first using the current scope - if (currentClass) { - type = findTypeEntryUsingContext(currentClass, qualifiedName); - - // 5.1.1 - Try using the class parents' scopes - if (!type && d && !currentClass->baseClassNames().isEmpty()) { - const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); - for (const AbstractMetaClass *cls : baseClasses) { - type = findTypeEntryUsingContext(cls, qualifiedName); - if (type) - break; - } - } - } - - // 5.2 - Try without scope - if (!type) - type = TypeDatabase::instance()->findType(qualifiedName); - - // 6. No? Try looking it up as a flags type - if (!type) - type = TypeDatabase::instance()->findFlagsType(qualifiedName); - - // 7. No? Try looking it up as a container type - if (!type) - type = TypeDatabase::instance()->findContainerType(name); - - // 8. No? Check if the current class is a template and this type is one - // of the parameters. - if (!type && currentClass) { - const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); - for (TypeEntry *te : template_args) { - if (te->name() == qualifiedName) - type = te; - } - } - - if (!type) { + const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d); + if (types.isEmpty()) { if (errorMessageIn) { *errorMessageIn = msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName)); @@ -2284,11 +2247,10 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo return nullptr; } - // These are only implicit and should not appear in code... - Q_ASSERT(!type->isInterface()); + const TypeEntry *type = types.constFirst(); + const TypeEntry::Type typeEntryType = type->type(); - auto *metaType = new AbstractMetaType; - metaType->setTypeEntry(type); + QScopedPointer<AbstractMetaType> metaType(new AbstractMetaType); metaType->setIndirectionsV(typeInfo.indirectionsV()); metaType->setReferenceType(typeInfo.referenceType()); metaType->setConstant(typeInfo.isConstant()); @@ -2299,23 +2261,78 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo for (int t = 0, size = templateArguments.size(); t < size; ++t) { const TypeInfo &ti = templateArguments.at(t); AbstractMetaType *targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); + // For non-type template parameters, create a dummy type entry on the fly + // as is done for classes. + if (!targType) { + const QString value = ti.qualifiedName().join(colonColon()); + if (isNumber(value)) { + TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry()); + targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); + } + } if (!targType) { if (errorMessageIn) *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage); - delete metaType; return nullptr; } metaType->addInstantiation(targType, true); } + if (types.size() > 1) { + const bool sameType = std::all_of(types.cbegin() + 1, types.cend(), + [typeEntryType](const TypeEntry *e) { + return e->type() == typeEntryType; }); + if (!sameType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousVaryingTypesFound(qualifiedName, types); + return nullptr; + } + // Ambiguous primitive/smart pointer types are possible (when + // including type systems). + if (typeEntryType != TypeEntry::PrimitiveType + && typeEntryType != TypeEntry::SmartPointerType) { + if (errorMessageIn) + *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types); + return nullptr; + } + } + + if (typeEntryType == TypeEntry::SmartPointerType) { + // Find a matching instantiation + if (metaType->instantiations().size() != 1) { + if (errorMessageIn) + *errorMessageIn = msgInvalidSmartPointerType(_typei); + return nullptr; + } + auto instantiationType = metaType->instantiations().constFirst()->typeEntry(); + if (instantiationType->type() == TypeEntry::TemplateArgumentType) { + // Member functions of the template itself, SharedPtr(const SharedPtr &) + type = instantiationType; + } else { + auto it = std::find_if(types.cbegin(), types.cend(), + [instantiationType](const TypeEntry *e) { + auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e); + return smartPtr->matchesInstantiation(instantiationType); + }); + if (it == types.cend()) { + if (errorMessageIn) + *errorMessageIn = msgCannotFindSmartPointerInstantion(_typei); + return nullptr; + } + type =*it; + } + } + + metaType->setTypeEntry(type); + // The usage pattern *must* be decided *after* the possible template // instantiations have been determined, or else the absence of // such instantiations will break the caching scheme of // AbstractMetaType::cppSignature(). metaType->decideUsagePattern(); - return metaType; + return metaType.take(); } AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, @@ -2626,14 +2643,11 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, // "template <int R, int C> Matrix<R, C>" and subclass // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of // EnumValueTypeEntry for the integer values encountered on the fly. - const bool isNumber = std::all_of(typeName.cbegin(), typeName.cend(), - [](QChar c) { return c.isDigit(); }); - if (isNumber) { + if (isNumber(typeName)) { t = typeDb->findType(typeName); if (!t) { - t = new ConstantValueTypeEntry(typeName, subclass->typeEntry()->typeSystemTypeEntry()); - t->setCodeGeneration(0); - typeDb->addType(t); + auto parent = subclass->typeEntry()->typeSystemTypeEntry(); + t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent); } } else { QStringList possibleNames; @@ -2770,7 +2784,6 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, subclass->setTemplateBaseClass(templateClass); subclass->setTemplateBaseClassInstantiations(templateTypes); - subclass->setInterfaces(templateClass->interfaces()); subclass->setBaseClass(templateClass->baseClass()); return true; @@ -2848,11 +2861,9 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) QQueue<AbstractMetaClass*> baseClasses; if (cls->baseClass()) baseClasses.enqueue(cls->baseClass()); - baseClasses << cls->interfaces().toList(); while (!baseClasses.isEmpty()) { AbstractMetaClass* currentClass = baseClasses.dequeue(); - baseClasses << currentClass->interfaces().toList(); if (currentClass->baseClass()) baseClasses.enqueue(currentClass->baseClass()); @@ -2897,7 +2908,7 @@ static void writeRejectLogFile(const QString &name, for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { - s << QString(72, QLatin1Char('*')) << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl; switch (reason) { case AbstractMetaBuilder::NotInTypeSystem: s << "Not in type system"; @@ -2930,16 +2941,16 @@ static void writeRejectLogFile(const QString &name, break; } - s << endl; + s << Qt::endl; for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin(); it != rejects.constEnd(); ++it) { if (it.value() != reason) continue; - s << " - " << it.key() << endl; + s << " - " << it.key() << Qt::endl; } - s << QString(72, QLatin1Char('*')) << endl << endl; + s << QString(72, QLatin1Char('*')) << Qt::endl << Qt::endl; } } @@ -3004,10 +3015,6 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const const AbstractMetaClassList &bases = getBaseClasses(clazz); for (AbstractMetaClass *baseClass : bases) { - // Fix polymorphic expression - if (clazz->baseClass() == baseClass) - clazz->setBaseClass(baseClass); - const auto baseIt = map.constFind(baseClass); if (baseIt!= map.cend()) graph.addEdge(baseIt.value(), classIndex); @@ -3048,8 +3055,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } else { for (int i : qAsConst(unmappedResult)) { Q_ASSERT(reverseMap.contains(i)); - if (!reverseMap[i]->isInterface()) - result << reverseMap[i]; + result << reverseMap[i]; } } @@ -3100,9 +3106,9 @@ AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractM return ret; } -void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader) +void AbstractMetaBuilder::setGlobalHeaders(const QFileInfoList &globalHeaders) { - d->m_globalHeader = QFileInfo(globalHeader); + d->m_globalHeaders = globalHeaders; } void AbstractMetaBuilder::setHeaderPaths(const HeaderPaths &hp) @@ -3140,23 +3146,26 @@ static bool matchHeader(const QString &headerPath, const QString &fileName) && fileName.startsWith(headerPath, caseSensitivity); } -void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const +void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &path) const { - auto it = m_resolveIncludeHash.find(fileName); + auto it = m_resolveIncludeHash.find(path); if (it == m_resolveIncludeHash.end()) { - QFileInfo info(fileName); - if (m_globalHeader.fileName() == info.fileName()) + QFileInfo info(path); + const QString fileName = info.fileName(); + if (std::any_of(m_globalHeaders.cbegin(), m_globalHeaders.cend(), + [fileName] (const QFileInfo &fi) { + return fi.fileName() == fileName; })) { return; + } int bestMatchLength = 0; for (const auto &headerPath : m_headerPaths) { - if (headerPath.size() > bestMatchLength && matchHeader(headerPath, fileName)) + if (headerPath.size() > bestMatchLength && matchHeader(headerPath, path)) bestMatchLength = headerPath.size(); } const QString include = bestMatchLength > 0 - ? fileName.right(fileName.size() - bestMatchLength - 1) - : info.fileName(); - it = m_resolveIncludeHash.insert(fileName, {Include::IncludePath, include}); + ? path.right(path.size() - bestMatchLength - 1) : fileName; + it = m_resolveIncludeHash.insert(path, {Include::IncludePath, include}); } te->setInclude(it.value()); } @@ -3181,7 +3190,7 @@ static void debugFormatSequence(QDebug &d, const char *key, const Container& c, void AbstractMetaBuilder::formatDebug(QDebug &debug) const { - debug << "m_globalHeader=" << d->m_globalHeader.absoluteFilePath(); + debug << "m_globalHeader=" << d->m_globalHeaders; debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n"); debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n"); if (const int scopeCount = d->m_scopes.size()) { diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index 93b9d9fd2..37022a544 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -35,6 +35,8 @@ #include "clangparser/compilersupport.h" +#include <QFileInfoList> + QT_FORWARD_DECLARE_CLASS(QIODevice) class AbstractMetaBuilderPrivate; @@ -85,7 +87,7 @@ public: * so any class declared under this header wont have the include file * filled. */ - void setGlobalHeader(const QString& globalHeader); + void setGlobalHeaders(const QFileInfoList& globalHeaders); void setHeaderPaths(const HeaderPaths &h); void setSkipDeprecated(bool value); diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index be73697f0..2686ebacb 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -147,6 +147,9 @@ public: AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); + static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name, + AbstractMetaClass *currentClass = nullptr, + AbstractMetaBuilderPrivate *d = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); @@ -167,7 +170,7 @@ public: void sortLists(); AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); - void setInclude(TypeEntry *te, const QString &fileName) const; + void setInclude(TypeEntry *te, const QString &path) const; void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); void fillAddedFunctions(AbstractMetaClass *metaClass); @@ -194,7 +197,7 @@ public: QSet<AbstractMetaClass *> m_setupInheritanceDone; QString m_logDirectory; - QFileInfo m_globalHeader; + QFileInfoList m_globalHeaders; QStringList m_headerPaths; mutable QHash<QString, Include> m_resolveIncludeHash; bool m_skipDeprecated = false; diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index ad694eb4f..390143cda 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -80,15 +80,10 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, { if (pred(klass)) return klass; - if (auto base = klass->baseClass()) { + for (auto base : klass->baseClasses()) { if (auto r = recurseClassHierarchy(base, pred)) return r; } - const auto interfaces = klass->interfaces(); - for (auto i : interfaces) { - if (auto r = recurseClassHierarchy(i, pred)) - return r; - } return nullptr; } @@ -268,7 +263,7 @@ QString AbstractMetaType::pythonSignature() const // PYSIDE-921: Handle container returntypes correctly. // This is now a clean reimplementation. if (m_cachedPythonSignature.isEmpty()) - m_cachedPythonSignature = formatPythonSignature(false); + m_cachedPythonSignature = formatPythonSignature(); return m_cachedPythonSignature; } @@ -310,10 +305,6 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isValue()) return indirections() == 1 ? ValuePointerPattern : ValuePattern; - if (ReportHandler::isDebug(ReportHandler::FullDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("native pointer pattern for '%1'").arg(cppSignature()); - } return NativePointerPattern; } @@ -531,7 +522,7 @@ bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const */ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const { - CompareResult result = nullptr; + CompareResult result; // Enclosing class... if (ownerClass() == other->ownerClass()) @@ -825,8 +816,8 @@ bool AbstractMetaFunction::allowThread() const result = false; break; } - if (!result) - qCDebug(lcShiboken).noquote() << msgDisallowThread(this); + if (!result && ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCInfo(lcShiboken).noquote() << msgDisallowThread(this); return result; } @@ -950,9 +941,6 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC (implementor == implementingClass() && !mods.isEmpty())) { break; } - const AbstractMetaClassList &interfaces = implementor->interfaces(); - for (const AbstractMetaClass *interface : interfaces) - mods += this->modifications(interface); implementor = implementor->baseClass(); } return mods; @@ -1367,44 +1355,6 @@ bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const } /******************************************************************************* - * Constructs an interface based on the functions and enums in this - * class and returns it... - */ -AbstractMetaClass *AbstractMetaClass::extractInterface() -{ - Q_ASSERT(typeEntry()->designatedInterface()); - - if (!m_extractedInterface) { - auto *iface = new AbstractMetaClass; - iface->setAttributes(attributes()); - iface->setBaseClass(nullptr); - - iface->setTypeEntry(typeEntry()->designatedInterface()); - - for (AbstractMetaFunction *function : qAsConst(m_functions)) { - if (!function->isConstructor()) - iface->addFunction(function->copy()); - } - -// iface->setEnums(enums()); -// setEnums(AbstractMetaEnumList()); - - for (const AbstractMetaField *field : qAsConst(m_fields)) { - if (field->isPublic()) { - AbstractMetaField *new_field = field->copy(); - new_field->setEnclosingClass(iface); - iface->addField(new_field); - } - } - - m_extractedInterface = iface; - addInterface(iface); - } - - return m_extractedInterface; -} - -/******************************************************************************* * Returns a list of all the functions with a given name */ AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const @@ -1426,10 +1376,6 @@ AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const { FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; - // Interfaces don't implement functions - if (isInterface()) - default_flags |= ClassImplements; - // Only public functions in final classes // default_flags |= isFinal() ? WasPublic : 0; FunctionQueryOptions public_flags; @@ -1606,11 +1552,19 @@ QString AbstractMetaClass::name() const return m_typeEntry->targetLangEntryName(); } +void AbstractMetaClass::addBaseClass(AbstractMetaClass *baseClass) +{ + Q_ASSERT(baseClass); + m_baseClasses.append(baseClass); + m_isPolymorphic |= baseClass->isPolymorphic(); +} + void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) { - m_baseClass = baseClass; - if (baseClass) + if (baseClass) { + m_baseClasses.prepend(baseClass); m_isPolymorphic |= baseClass->isPolymorphic(); + } } QString AbstractMetaClass::package() const @@ -1618,11 +1572,6 @@ QString AbstractMetaClass::package() const return m_typeEntry->targetLangPackage(); } -bool AbstractMetaClass::isInterface() const -{ - return m_typeEntry->isInterface(); -} - bool AbstractMetaClass::isNamespace() const { return m_typeEntry->isNamespace(); @@ -1731,7 +1680,7 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList bool AbstractMetaClass::deleteInMainThread() const { return typeEntry()->deleteInMainThread() - || (m_baseClass && m_baseClass->deleteInMainThread()); + || (!m_baseClasses.isEmpty() && m_baseClasses.constFirst()->deleteInMainThread()); } static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) @@ -1860,6 +1809,14 @@ const AbstractMetaFunction *AbstractMetaField::setter() const return m_setter; } +const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const +{ + auto result = m_enclosingClass; + while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) + result = result->enclosingClass(); + return result; +} + const AbstractMetaFunction *AbstractMetaField::getter() const { if (!m_getter) { @@ -2108,6 +2065,16 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue if ((query & GenerateExceptionHandling) && !f->generateExceptionHandling()) return false; + if (query.testFlag(GetAttroFunction) + && f->functionType() != AbstractMetaFunction::GetAttroFunction) { + return false; + } + + if (query.testFlag(SetAttroFunction) + && f->functionType() != AbstractMetaFunction::SetAttroFunction) { + return false; + } + return true; } @@ -2148,57 +2115,6 @@ AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const return queryFunctions(Signals | Visible | NotRemovedFromTargetLang); } -/** - * Adds the specified interface to this class by adding all the - * functions in the interface to this class. - */ -void AbstractMetaClass::addInterface(AbstractMetaClass *interface) -{ - Q_ASSERT(!m_interfaces.contains(interface)); - m_interfaces << interface; - - m_isPolymorphic |= interface->isPolymorphic(); - - if (m_extractedInterface && m_extractedInterface != interface) - m_extractedInterface->addInterface(interface); - - -#if 0 - const AbstractMetaFunctionList &funcs = interface->functions(); - for (AbstractMetaFunction *function : funcs) - if (!hasFunction(function) && !function->isConstructor()) { - AbstractMetaFunction *cpy = function->copy(); - cpy->setImplementingClass(this); - - // Setup that this function is an interface class. - cpy->setInterfaceClass(interface); - *cpy += AbstractMetaAttributes::InterfaceFunction; - - // Copy the modifications in interface into the implementing classes. - const FunctionModificationList &mods = function->modifications(interface); - for (const FunctionModification &mod : mods) - m_typeEntry->addFunctionModification(mod); - - // It should be mostly safe to assume that when we implement an interface - // we don't "pass on" pure virtual functions to our sublcasses... -// *cpy -= AbstractMetaAttributes::Abstract; - - addFunction(cpy); - } -#endif - -} - - -void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) -{ - m_interfaces = interfaces; - for (const AbstractMetaClass *interface : interfaces) { - if (interface) - m_isPolymorphic |= interface->isPolymorphic(); - } -} - AbstractMetaField *AbstractMetaClass::findField(const QString &name) const { return AbstractMetaField::find(m_fields, name); @@ -2208,10 +2124,6 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) { if (AbstractMetaEnum *e = findByName(m_enums, enumName)) return e; - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnum(enumName); - return nullptr; } @@ -2224,10 +2136,6 @@ AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValue if (AbstractMetaEnumValue *v = e->findEnumValue(enumValueName)) return v; } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumValue(enumValueName); - if (baseClass()) return baseClass()->findEnumValue(enumValueName); @@ -2274,32 +2182,23 @@ void AbstractMetaClass::fixFunctions() m_functionsFixed = true; - AbstractMetaClass *superClass = baseClass(); AbstractMetaFunctionList funcs = functions(); - if (superClass) + for (auto superClass : m_baseClasses) { superClass->fixFunctions(); - int iface_idx = 0; - while (superClass || iface_idx < interfaces().size()) { // Since we always traverse the complete hierarchy we are only // interrested in what each super class implements, not what // we may have propagated from their base classes again. AbstractMetaFunctionList superFuncs; - if (superClass) { - // Super classes can never be final - if (superClass->isFinalInTargetLang()) { - qCWarning(lcShiboken).noquote().nospace() - << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; - *superClass -= AbstractMetaAttributes::FinalInTargetLang; - } - superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); - AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - } else { - superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); - AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; + // Super classes can never be final + if (superClass->isFinalInTargetLang()) { + qCWarning(lcShiboken).noquote().nospace() + << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; + *superClass -= AbstractMetaAttributes::FinalInTargetLang; } + superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); + AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); + superFuncs += virtuals; QSet<AbstractMetaFunction *> funcsToAdd; for (auto sf : qAsConst(superFuncs)) { @@ -2428,11 +2327,6 @@ void AbstractMetaClass::fixFunctions() (*copy) += AddedMethod; funcs.append(copy); } - - if (superClass) - superClass = superClass->baseClass(); - else - iface_idx++; } bool hasPrivateConstructors = false; @@ -2531,7 +2425,7 @@ QString AbstractMetaType::formatSignature(bool minimal) const return result; } -QString AbstractMetaType::formatPythonSignature(bool minimal) const +QString AbstractMetaType::formatPythonSignature() const { /* * This is a version of the above, more suitable for Python. @@ -2554,7 +2448,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const result += package() + QLatin1Char('.'); if (isArray()) { // Build nested array dimensions a[2][3] in correct order - result += m_arrayElementType->formatPythonSignature(true); + result += m_arrayElementType->formatPythonSignature(); const int arrayPos = result.indexOf(QLatin1Char('[')); if (arrayPos != -1) result.insert(arrayPos, formatArraySize(m_arrayElementCount)); @@ -2568,7 +2462,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const for (int i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) result += QLatin1String(", "); - result += m_instantiations.at(i)->formatPythonSignature(true); + result += m_instantiations.at(i)->formatPythonSignature(); } result += QLatin1Char(']'); } @@ -2685,6 +2579,63 @@ AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &cla } #ifndef QT_NO_DEBUG_STREAM + +void AbstractMetaClass::format(QDebug &d) const +{ + if (d.verbosity() > 2) + d << static_cast<const void *>(this) << ", "; + d << '"' << qualifiedCppName(); + if (const int count = m_templateArgs.size()) { + for (int i = 0; i < count; ++i) + d << (i ? ',' : '<') << m_templateArgs.at(i)->qualifiedCppName(); + d << '>'; + } + d << '"'; + if (isNamespace()) + d << " [namespace]"; + if (attributes() & AbstractMetaAttributes::FinalCppClass) + d << " [final]"; + if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) + d << " [deprecated]"; + if (!m_baseClasses.isEmpty()) { + d << ", inherits "; + for (auto b : m_baseClasses) + d << " \"" << b->name() << '"'; + } + if (auto templateBase = templateBaseClass()) { + const auto instantiatedTypes = templateBaseClassInstantiations(); + d << ", instantiates \"" << templateBase->name(); + for (int i = 0, count = instantiatedTypes.size(); i < count; ++i) + d << (i ? ',' : '<') << instantiatedTypes.at(i)->name(); + d << ">\""; + } +} + +void AbstractMetaClass::formatMembers(QDebug &d) const +{ + if (!m_enums.isEmpty()) + d << ", enums[" << m_enums.size() << "]=" << m_enums; + if (!m_functions.isEmpty()) { + const int count = m_functions.size(); + d << ", functions=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaFunctionBrief(d, m_functions.at(i)); + } + d << ')'; + } + if (const int count = m_fields.size()) { + d << ", fields=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaField(d, m_fields.at(i)); + } + d << ')'; + } +} + QDebug operator<<(QDebug d, const AbstractMetaClass *ac) { QDebugStateSaver saver(d); @@ -2692,57 +2643,9 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) d.nospace(); d << "AbstractMetaClass("; if (ac) { - d << '"' << ac->fullName() << '"'; - if (ac->attributes() & AbstractMetaAttributes::FinalCppClass) - d << " [final]"; - if (ac->attributes().testFlag(AbstractMetaAttributes::Deprecated)) - d << " [deprecated]"; - if (ac->m_baseClass) - d << ", inherits \"" << ac->m_baseClass->name() << '"'; - if (ac->m_templateBaseClass) - d << ", inherits template \"" << ac->m_templateBaseClass->name() << '"'; - const AbstractMetaEnumList &enums = ac->enums(); - if (!enums.isEmpty()) - d << ", enums[" << enums.size() << "]=" << enums; - const AbstractMetaFunctionList &functions = ac->functions(); - if (!functions.isEmpty()) { - const int count = functions.size(); - d << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) - d << functions.at(i); - else -#endif - formatMetaFunctionBrief(d, functions.at(i)); - } - d << ')'; - } - const AbstractMetaFieldList &fields = ac->fields(); - if (!fields.isEmpty()) { - const int count = fields.size(); - d << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaField(d, fields.at(i)); - } - d << ')'; - } - const auto &templateArguments = ac->templateArguments(); - if (const int count = templateArguments.size()) { - d << ", templateArguments=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - d << templateArguments.at(i); - } - d << ')'; - } - - + ac->format(d); + if (d.verbosity() > 2) + ac->formatMembers(d); } else { d << '0'; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 166e7d0cb..00f137100 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -538,7 +538,7 @@ public: private: TypeUsagePattern determineUsagePattern() const; QString formatSignature(bool minimal) const; - QString formatPythonSignature(bool minimal) const; + QString formatPythonSignature() const; const TypeEntry *m_typeEntry = nullptr; AbstractMetaTypeList m_instantiations; @@ -704,25 +704,26 @@ private: friend class AbstractMetaClass; }; +class EnclosingClassMixin { +public: + const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; } + void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; } + const AbstractMetaClass *targetLangEnclosingClass() const; + +private: + const AbstractMetaClass *m_enclosingClass = nullptr; +}; + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaArgument *aa); #endif -class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes +class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaField(); ~AbstractMetaField(); - const AbstractMetaClass *enclosingClass() const - { - return m_class; - } - void setEnclosingClass(const AbstractMetaClass *cls) - { - m_class = cls; - } - const AbstractMetaFunction *getter() const; const AbstractMetaFunction *setter() const; @@ -741,7 +742,6 @@ public: private: mutable AbstractMetaFunction *m_getter = nullptr; mutable AbstractMetaFunction *m_setter = nullptr; - const AbstractMetaClass *m_class = nullptr; }; #ifndef QT_NO_DEBUG_STREAM @@ -763,7 +763,9 @@ public: SignalFunction, EmptyFunction, SlotFunction, - GlobalScopeFunction + GlobalScopeFunction, + GetAttroFunction, + SetAttroFunction }; Q_ENUM(FunctionType) @@ -1179,7 +1181,7 @@ private: Documentation m_doc; }; -class AbstractMetaEnum : public AbstractMetaAttributes +class AbstractMetaEnum : public AbstractMetaAttributes, public EnclosingClassMixin { public: AbstractMetaEnum(); @@ -1234,23 +1236,12 @@ public: m_typeEntry = entry; } - AbstractMetaClass *enclosingClass() const - { - return m_class; - } - - void setEnclosingClass(AbstractMetaClass *c) - { - m_class = c; - } - bool isSigned() const { return m_signed; } void setSigned(bool s) { m_signed = s; } private: AbstractMetaEnumValueList m_enumValues; EnumTypeEntry *m_typeEntry = nullptr; - AbstractMetaClass *m_class = nullptr; EnumKind m_enumKind = CEnum; uint m_hasQenumsDeclaration : 1; @@ -1261,7 +1252,7 @@ private: QDebug operator<<(QDebug d, const AbstractMetaEnum *ae); #endif -class AbstractMetaClass : public AbstractMetaAttributes +class AbstractMetaClass : public AbstractMetaAttributes, public EnclosingClassMixin { Q_GADGET public: @@ -1282,7 +1273,9 @@ public: VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang OperatorOverloads = 0x2000000, // Only functions that are operator overloads - GenerateExceptionHandling = 0x4000000 + GenerateExceptionHandling = 0x4000000, + GetAttroFunction = 0x8000000, + SetAttroFunction = 0x10000000 }; Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption) Q_FLAG(FunctionQueryOption) @@ -1306,7 +1299,6 @@ public: AbstractMetaClass(); ~AbstractMetaClass(); - AbstractMetaClass *extractInterface(); void fixFunctions(); AbstractMetaFunctionList functions() const @@ -1444,13 +1436,6 @@ public: AbstractMetaEnum *findEnum(const QString &enumName); AbstractMetaEnumValue *findEnumValue(const QString &enumName); - AbstractMetaClassList interfaces() const - { - return m_interfaces; - } - void addInterface(AbstractMetaClass *interface); - void setInterfaces(const AbstractMetaClassList &interface); - QString fullName() const { return package() + QLatin1Char('.') + name(); @@ -1464,32 +1449,24 @@ public: QString baseClassName() const { - return m_baseClass ? m_baseClass->name() : QString(); + return m_baseClasses.isEmpty() ? QString() : m_baseClasses.constFirst()->name(); } AbstractMetaClass *baseClass() const { - return m_baseClass; + return m_baseClasses.value(0, nullptr); } + const AbstractMetaClassList &baseClasses() const { return m_baseClasses; } + void addBaseClass(AbstractMetaClass *base_class); void setBaseClass(AbstractMetaClass *base_class); - const AbstractMetaClass *enclosingClass() const - { - return m_enclosingClass; - } - /** * \return the namespace from another package which this namespace extends. */ AbstractMetaClass *extendedNamespace() const { return m_extendedNamespace; } void setExtendedNamespace(AbstractMetaClass *e) { m_extendedNamespace = e; } - void setEnclosingClass(AbstractMetaClass *cl) - { - m_enclosingClass = cl; - } - const AbstractMetaClassList& innerClasses() const { return m_innerClasses; @@ -1507,8 +1484,6 @@ public: QString package() const; - bool isInterface() const; - bool isNamespace() const; bool isQObject() const; @@ -1709,6 +1684,8 @@ public: private: #ifndef QT_NO_DEBUG_STREAM + void format(QDebug &d) const; + void formatMembers(QDebug &d) const; friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); #endif uint m_hasVirtuals : 1; @@ -1727,21 +1704,19 @@ private: uint m_hasToStringCapability : 1; const AbstractMetaClass *m_enclosingClass = nullptr; - AbstractMetaClass *m_baseClass = nullptr; + AbstractMetaClassList m_baseClasses; // Real base classes after setting up inheritance AbstractMetaClass *m_extendedNamespace = nullptr; const AbstractMetaClass *m_templateBaseClass = nullptr; AbstractMetaFunctionList m_functions; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; - AbstractMetaClassList m_interfaces; - AbstractMetaClass *m_extractedInterface = nullptr; QVector<QPropertySpec *> m_propertySpecs; AbstractMetaClassList m_innerClasses; AbstractMetaFunctionList m_externalConversionOperators; - QStringList m_baseClassNames; + QStringList m_baseClassNames; // Base class names from C++, including rejected QVector<TypeEntry *> m_templateArgs; ComplexTypeEntry *m_typeEntry = nullptr; // FunctionModelItem m_qDebugStreamFunction; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index 78fa9e313..530ed0252 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -82,9 +82,9 @@ void ApiExtractor::setLogDirectory(const QString& logDir) m_logDirectory = logDir; } -void ApiExtractor::setCppFileName(const QString& cppFileName) +void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName) { - m_cppFileName = cppFileName; + m_cppFileNames = cppFileName; } void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) @@ -92,11 +92,6 @@ void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) m_typeSystemFileName = typeSystemFileName; } -void ApiExtractor::setDebugLevel(ReportHandler::DebugLevel debugLevel) -{ - ReportHandler::setDebugLevel(debugLevel); -} - void ApiExtractor::setSkipDeprecated(bool value) { m_skipDeprecated = value; @@ -166,24 +161,6 @@ ContainerTypeEntryList ApiExtractor::containerTypes() const return TypeDatabase::instance()->containerTypes(); } -static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) -{ - const AbstractMetaEnum *result = nullptr; - for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->typeEntry() == typeEntry) { - result = metaEnum; - break; - } - } - if (result) - break; - result = findEnumOnClasses(metaClass->innerClasses(), typeEntry); - } - return result; -} - const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const { return m_builder->findEnum(typeEntry); @@ -205,8 +182,9 @@ bool ApiExtractor::run() return false; } - const QString pattern = QDir::tempPath() + QLatin1Char('/') + - QFileInfo(m_cppFileName).baseName() + QStringLiteral("_XXXXXX.hpp"); + const QString pattern = QDir::tempPath() + QLatin1Char('/') + + m_cppFileNames.constFirst().baseName() + + QStringLiteral("_XXXXXX.hpp"); QTemporaryFile ppFile(pattern); bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); // make sure that a tempfile can be written @@ -215,14 +193,16 @@ bool ApiExtractor::run() << ": " << qPrintable(ppFile.errorString()) << '\n'; return false; } - ppFile.write("#include \""); - ppFile.write(m_cppFileName.toLocal8Bit()); - ppFile.write("\"\n"); + for (const auto &cppFileName : qAsConst(m_cppFileNames)) { + ppFile.write("#include \""); + ppFile.write(cppFileName.absoluteFilePath().toLocal8Bit()); + ppFile.write("\"\n"); + } const QString preprocessedCppFileName = ppFile.fileName(); ppFile.close(); m_builder = new AbstractMetaBuilder; m_builder->setLogDirectory(m_logDirectory); - m_builder->setGlobalHeader(m_cppFileName); + m_builder->setGlobalHeaders(m_cppFileNames); m_builder->setSkipDeprecated(m_skipDeprecated); m_builder->setHeaderPaths(m_includePaths); QByteArrayList arguments; @@ -230,8 +210,11 @@ bool ApiExtractor::run() for (const HeaderPath &headerPath : qAsConst(m_includePaths)) arguments.append(HeaderPath::includeOption(headerPath)); arguments.append(QFile::encodeName(preprocessedCppFileName)); - qCDebug(lcShiboken) << __FUNCTION__ << arguments - << "level=" << int(m_languageLevel); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + qCInfo(lcShiboken).noquote().nospace() + << "clang language level: " << int(m_languageLevel) + << "\nclang arguments: " << arguments; + } const bool result = m_builder->build(arguments, m_languageLevel); if (!result) autoRemove = false; @@ -273,8 +256,10 @@ QDebug operator<<(QDebug d, const ApiExtractor &ae) QDebugStateSaver saver(d); d.noquote(); d.nospace(); - d << "ApiExtractor(typeSystem=\"" << ae.typeSystem() << "\", cppFileName=\"" - << ae.cppFileName() << ", "; + if (ReportHandler::debugLevel() >= ReportHandler::FullDebug) + d.setVerbosity(3); // Trigger verbose output of AbstractMetaClass + d << "ApiExtractor(typeSystem=\"" << ae.typeSystem() << "\", cppFileNames=\"" + << ae.cppFileNames() << ", "; ae.m_builder->formatDebug(d); d << ')'; return d; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.h b/sources/shiboken2/ApiExtractor/apiextractor.h index c8f50f2a5..f6dd2ba8e 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.h +++ b/sources/shiboken2/ApiExtractor/apiextractor.h @@ -29,7 +29,6 @@ #ifndef APIEXTRACTOR_H #define APIEXTRACTOR_H -#include "reporthandler.h" #include "dependency.h" #include "abstractmetalang_typedefs.h" #include "apiextractormacros.h" @@ -37,6 +36,7 @@ #include "typedatabase_typedefs.h" #include "typesystem_typedefs.h" #include "clangparser/compilersupport.h" +#include <QFileInfoList> #include <QStringList> class AbstractMetaBuilder; @@ -65,9 +65,8 @@ public: void setTypeSystem(const QString& typeSystemFileName); QString typeSystem() const { return m_typeSystemFileName; } - void setCppFileName(const QString& cppFileName); - QString cppFileName() const { return m_cppFileName; } - void setDebugLevel(ReportHandler::DebugLevel debugLevel); + void setCppFileNames(const QFileInfoList &cppFileNames); + QFileInfoList cppFileNames() const { return m_cppFileNames; } void setSkipDeprecated(bool value); void setSuppressWarnings(bool value); void setSilent(bool value); @@ -97,7 +96,7 @@ public: bool run(); private: QString m_typeSystemFileName; - QString m_cppFileName; + QFileInfoList m_cppFileNames; HeaderPaths m_includePaths; AbstractMetaBuilder* m_builder = nullptr; QString m_logDirectory; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index d52e4672b..1eaa36540 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -191,6 +191,8 @@ public: bool addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const; void addTypeDef(const CXCursor &cursor, const CXType &cxType); + void startTemplateTypeAlias(const CXCursor &cursor); + void endTemplateTypeAlias(const CXCursor &typeAliasCursor); TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const; TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const; @@ -216,12 +218,16 @@ public: CursorTypedefHash m_cursorTypedefHash; mutable TypeInfoHash m_typeInfoHash; // Cache type information + mutable QHash<QString, TemplateTypeAliasModelItem> m_templateTypeAliases; ClassModelItem m_currentClass; EnumModelItem m_currentEnum; FunctionModelItem m_currentFunction; ArgumentModelItem m_currentArgument; VariableModelItem m_currentField; + TemplateTypeAliasModelItem m_currentTemplateTypeAlias; + QByteArrayList m_systemIncludes; // files, like "memory" + QByteArrayList m_systemIncludePaths; // paths, like "/usr/include/Qt/" int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; @@ -464,6 +470,8 @@ void BuilderPrivate::addTemplateInstantiations(const CXType &type, // Finally, remove the list "<>" from the type name. const bool parsed = addTemplateInstantiationsRecursion(type, t) && !t->instantiations().isEmpty(); + if (!parsed) + t->setInstantiations({}); const QPair<int, int> pos = parsed ? parseTemplateArgumentList(*typeName, dummyTemplateArgumentHandler) : t->parseTemplateArgumentList(*typeName); @@ -550,6 +558,26 @@ void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType) m_cursorTypedefHash.insert(cursor, item); } +void BuilderPrivate::startTemplateTypeAlias(const CXCursor &cursor) +{ + const QString target = getCursorSpelling(cursor); + m_currentTemplateTypeAlias.reset(new _TemplateTypeAliasModelItem(m_model, target)); + setFileName(cursor, m_currentTemplateTypeAlias.data()); + m_currentTemplateTypeAlias->setScope(m_scope); +} + +void BuilderPrivate::endTemplateTypeAlias(const CXCursor &typeAliasCursor) +{ + CXType type = clang_getTypedefDeclUnderlyingType(typeAliasCursor); + // Usually "<elaborated>std::list<T>" or "<unexposed>Container1<T>", + // as obtained with parser of PYSIDE-323 + if (type.kind == CXType_Unexposed || type.kind == CXType_Elaborated) { + m_currentTemplateTypeAlias->setType(createTypeInfo(type)); + m_scopeStack.back()->addTemplateTypeAlias(m_currentTemplateTypeAlias); + } + m_currentTemplateTypeAlias.reset(); +} + // extract an expression from the cursor via source // CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2) QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const @@ -592,13 +620,52 @@ long clang_EnumDecl_isScoped4(BaseVisitor *bv, const CXCursor &cursor) } #endif // CLANG_NO_ENUMDECL_ISSCOPED +// Resolve declaration and type of a base class + +struct TypeDeclaration +{ + CXType type; + CXCursor declaration; +}; + +static TypeDeclaration resolveBaseSpecifier(const CXCursor &cursor) +{ + Q_ASSERT(clang_getCursorKind(cursor) == CXCursor_CXXBaseSpecifier); + CXType inheritedType = clang_getCursorType(cursor); + CXCursor decl = clang_getTypeDeclaration(inheritedType); + if (inheritedType.kind != CXType_Unexposed) { + while (true) { + auto kind = clang_getCursorKind(decl); + if (kind != CXCursor_TypeAliasDecl && kind != CXCursor_TypedefDecl) + break; + inheritedType = clang_getTypedefDeclUnderlyingType(decl); + decl = clang_getTypeDeclaration(inheritedType); + } + } + return {inheritedType, decl}; +} + // Add a base class to the current class from CXCursor_CXXBaseSpecifier void BuilderPrivate::addBaseClass(const CXCursor &cursor) { - const CXType inheritedType = clang_getCursorType(cursor); // Note spelling has "struct baseClass", - QString baseClassName = getTypeName(inheritedType); // use type. - const CXCursor declCursor = clang_getTypeDeclaration(inheritedType); - const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor); + Q_ASSERT(clang_getCursorKind(cursor) == CXCursor_CXXBaseSpecifier); + // Note: spelling has "struct baseClass", use type + QString baseClassName; + const auto decl = resolveBaseSpecifier(cursor); + if (decl.type.kind == CXType_Unexposed) { + // The type is unexposed when the base class is a template type alias: + // "class QItemSelection : public QList<X>" where QList is aliased to QVector. + // Try to resolve via code model. + TypeInfo info = createTypeInfo(decl.type); + auto parentScope = m_scopeStack.at(m_scopeStack.size() - 2); // Current is class. + auto resolved = TypeInfo::resolveType(info, parentScope); + if (resolved != info) + baseClassName = resolved.toString(); + } + if (baseClassName.isEmpty()) + baseClassName = getTypeName(decl.type); + + auto it = m_cursorClassHash.constFind(decl.declaration); const CodeModel::AccessPolicy access = accessPolicy(clang_getCXXAccessSpecifier(cursor)); if (it == m_cursorClassHash.constEnd()) { // Set unqualified name. This happens in cases like "class X : public std::list<...>" @@ -695,6 +762,11 @@ static bool cStringStartsWith(const char *str, const char (&prefix)[N]) } #endif +static bool cStringStartsWith(const char *str, const QByteArray &prefix) +{ + return std::strncmp(prefix.constData(), str, int(prefix.size())) == 0; +} + bool BuilderPrivate::visitHeader(const char *cFileName) const { // Resolve OpenGL typedefs although the header is considered a system header. @@ -721,6 +793,16 @@ bool BuilderPrivate::visitHeader(const char *cFileName) const return true; } #endif // Q_OS_MACOS + if (baseName) { + for (const auto &systemInclude : m_systemIncludes) { + if (systemInclude == baseName) + return true; + } + } + for (const auto &systemIncludePath : m_systemIncludePaths) { + if (cStringStartsWith(cFileName, systemIncludePath)) + return true; + } return false; } @@ -743,6 +825,16 @@ bool Builder::visitLocation(const CXSourceLocation &location) const return result; } +void Builder::setSystemIncludes(const QByteArrayList &systemIncludes) +{ + for (const auto &i : systemIncludes) { + if (i.endsWith('/')) + d->m_systemIncludePaths.append(i); + else + d->m_systemIncludes.append(i); + } +} + FileModelItem Builder::dom() const { Q_ASSERT(!d->m_scopeStack.isEmpty()); @@ -766,6 +858,17 @@ static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) return result; } +static NamespaceType namespaceType(const CXCursor &cursor) +{ + if (clang_Cursor_isAnonymous(cursor)) + return NamespaceType::Anonymous; +#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 59 + if (clang_Cursor_isInlineNamespace(cursor)) + return NamespaceType::Inline; +#endif + return NamespaceType::Default; +} + static QString enumType(const CXCursor &cursor) { QString name = getCursorSpelling(cursor); // "enum Foo { v1, v2 };" @@ -904,6 +1007,9 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_Namespace: { + const auto type = namespaceType(cursor); + if (type == NamespaceType::Anonymous) + return Skip; const QString name = getCursorSpelling(cursor); const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); if (parentNamespaceItem.isNull()) { @@ -920,6 +1026,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); setFileName(cursor, namespaceItem.data()); namespaceItem->setScope(d->m_scope); + namespaceItem->setType(type); parentNamespaceItem->addNamespace(namespaceItem); d->pushScope(namespaceItem); } @@ -948,6 +1055,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) // Apply to function/member template? if (!d->m_currentFunction.isNull()) { d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); + } else if (!d->m_currentTemplateTypeAlias.isNull()) { + d->m_currentTemplateTypeAlias->addTemplateParameter(tItem); } else if (!d->m_currentClass.isNull()) { // Apply to class const QString &tplParmName = tItem->name(); if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass) @@ -963,13 +1072,19 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } } break; - case CXCursor_TypeAliasDecl: - case CXCursor_TypeAliasTemplateDecl: { // May contain nested CXCursor_TemplateTypeParameter - const CXType type = clang_getCanonicalType(clang_getCursorType(cursor)); - if (type.kind > CXType_Unexposed) - d->addTypeDef(cursor, type); - } - return Skip; + case CXCursor_TypeAliasTemplateDecl: + d->startTemplateTypeAlias(cursor); + break; + case CXCursor_TypeAliasDecl: // May contain nested CXCursor_TemplateTypeParameter + if (d->m_currentTemplateTypeAlias.isNull()) { + const CXType type = clang_getCanonicalType(clang_getCursorType(cursor)); + if (type.kind > CXType_Unexposed) + d->addTypeDef(cursor, type); + return Skip; + } else { + d->endTemplateTypeAlias(cursor); + } + break; case CXCursor_TypedefDecl: { auto underlyingType = clang_getTypedefDeclUnderlyingType(cursor); d->addTypeDef(cursor, underlyingType); @@ -1048,6 +1163,9 @@ bool Builder::endToken(const CXCursor &cursor) case CXCursor_ParmDecl: d->m_currentArgument.clear(); break; + case CXCursor_TypeAliasTemplateDecl: + d->m_currentTemplateTypeAlias.reset(); + break; default: break; } diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h index fa79acb2a..dc37dff0f 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h @@ -44,6 +44,8 @@ public: Builder(); ~Builder(); + void setSystemIncludes(const QByteArrayList &systemIncludes); + bool visitLocation(const CXSourceLocation &location) const override; StartTokenResult startToken(const CXCursor &cursor) override; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp index 8bee28cdf..df2476100 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp @@ -40,7 +40,7 @@ bool operator==(const CXCursor &c1, const CXCursor &c2) && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); } -uint qHash(const CXCursor &c, uint seed) +QtCompatHashFunctionType qHash(const CXCursor &c, QtCompatHashFunctionType seed) { return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; @@ -52,10 +52,10 @@ bool operator==(const CXType &t1, const CXType &t2) && t1.data[1] == t2.data[1]; } -uint qHash(const CXType &ct, uint seed) +QtCompatHashFunctionType qHash(const CXType &ct, QtCompatHashFunctionType seed) { - return uint(ct.kind) ^ uint(0xFFFFFFFF & quintptr(ct.data[0])) - ^ uint(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed; + return QtCompatHashFunctionType(ct.kind) ^ QtCompatHashFunctionType(0xFFFFFFFF & quintptr(ct.data[0])) + ^ QtCompatHashFunctionType(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed; } namespace clang { diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h index 738b51bb4..5f005bd5d 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h @@ -30,6 +30,7 @@ #define CLANGUTILS_H #include <clang-c/Index.h> +#include <qtcompat.h> #include <QtCore/QPair> #include <QtCore/QString> #include <QtCore/QStringList> @@ -40,10 +41,10 @@ QT_FORWARD_DECLARE_CLASS(QDebug) bool operator==(const CXCursor &c1, const CXCursor &c2); -uint qHash(const CXCursor &c, uint seed = 0); +QtCompatHashFunctionType qHash(const CXCursor &c, QtCompatHashFunctionType seed = 0); bool operator==(const CXType &t1, const CXType &t2); -uint qHash(const CXType &ct, uint seed); +QtCompatHashFunctionType qHash(const CXType &ct, QtCompatHashFunctionType seed); namespace clang { diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp index 188725da9..dac511003 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp @@ -356,12 +356,16 @@ QByteArrayList emulatedCompilerOptions() LanguageLevel emulatedCompilerLanguageLevel() { -#if defined(Q_CC_MSVC) && _MSC_VER > 1900 +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return LanguageLevel::Cpp17; +#else +# if defined(Q_CC_MSVC) && _MSC_VER > 1900 // Fixes constexpr errors in MSVC2017 library headers with Clang 4.1..5.X (0.45 == Clang 6). if (libClangVersion() < QVersionNumber(0, 45)) return LanguageLevel::Cpp1Z; -#endif // Q_CC_MSVC && _MSC_VER > 1900 +# endif // Q_CC_MSVC && _MSC_VER > 1900 return LanguageLevel::Cpp14; // otherwise, t.h is parsed as "C" +#endif // Qt 5 } struct LanguageLevelMapping diff --git a/sources/shiboken2/ApiExtractor/docparser.cpp b/sources/shiboken2/ApiExtractor/docparser.cpp index 532956d1a..cb5d85074 100644 --- a/sources/shiboken2/ApiExtractor/docparser.cpp +++ b/sources/shiboken2/ApiExtractor/docparser.cpp @@ -65,7 +65,7 @@ QString DocParser::execXQuery(const XQueryPtr &xquery, const QString& query) con QString errorMessage; const QString result = xquery->evaluate(query, &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return result; } @@ -138,12 +138,12 @@ R"(<xsl:template match="/"> QString errorMessage; const QString result = xsl_transform(xml, xsl, &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken, "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgXpathDocModificationError(mods, errorMessage))); if (result == xml) { const QString message = QLatin1String("Query did not result in any modifications to \"") + xml + QLatin1Char('"'); - qCWarning(lcShiboken, "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgXpathDocModificationError(mods, message))); } return result; diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.cpp b/sources/shiboken2/ApiExtractor/doxygenparser.cpp index 94c9ec7e0..7c15db1ca 100644 --- a/sources/shiboken2/ApiExtractor/doxygenparser.cpp +++ b/sources/shiboken2/ApiExtractor/doxygenparser.cpp @@ -80,7 +80,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) } if (doxyFilePath.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() + qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find doxygen file for class " << metaClass->name() << ", tried: " << QDir::toNativeSeparators(documentationDataDirectory()) << "/{struct|class|namespace}"<< doxyFileSuffix; @@ -90,7 +90,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) QString errorMessage; XQueryPtr xquery = XQuery::create(doxyFilePath, &errorMessage); if (xquery.isNull()) { - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } @@ -99,7 +99,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) QString classDoc = getDocumentation(xquery, classQuery, metaClass->typeEntry()->docModifications()); if (classDoc.isEmpty()) - qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, "class", metaClass->name(), classQuery))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, "class", metaClass->name(), classQuery))); metaClass->setDocumentation(classDoc); //Functions Documentation @@ -146,7 +146,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) } QString doc = getDocumentation(xquery, query, DocModificationList()); if (doc.isEmpty()) { - qCWarning(lcShiboken(), "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, func, query))); } func->setDocumentation(doc); @@ -163,7 +163,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) + field->name() + QLatin1String("\"]/../detaileddescription"); QString doc = getDocumentation(xquery, query, DocModificationList()); if (doc.isEmpty()) { - qCWarning(lcShiboken(), "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, field, query))); } field->setDocumentation(doc); @@ -176,7 +176,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) + meta_enum->name() + QLatin1String("\"]/.."); QString doc = getDocumentation(xquery, query, DocModificationList()); if (doc.isEmpty()) { - qCWarning(lcShiboken(), "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, meta_enum, query))); } meta_enum->setDocumentation(doc); @@ -189,7 +189,7 @@ Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ QString sourceFile = documentationDataDirectory() + QLatin1String("/indexpage.xml"); if (!QFile::exists(sourceFile)) { - qCWarning(lcShiboken).noquote().nospace() + qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find doxygen XML file for module " << name << ", tried: " << QDir::toNativeSeparators(sourceFile); return Documentation(); @@ -198,7 +198,7 @@ Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ QString errorMessage; XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage); if (xquery.isNull()) { - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return {}; } diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp index 95a80197e..53e20ebba 100644 --- a/sources/shiboken2/ApiExtractor/graph.cpp +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -101,7 +101,7 @@ bool Graph::containsEdge(int from, int to) void Graph::addEdge(int from, int to) { - Q_ASSERT(to < (int)m_d->edges.size()); + Q_ASSERT(to < m_d->edges.size()); m_d->edges[from].insert(to); } diff --git a/sources/shiboken2/ApiExtractor/include.cpp b/sources/shiboken2/ApiExtractor/include.cpp index d6a451992..6c2cce3a9 100644 --- a/sources/shiboken2/ApiExtractor/include.cpp +++ b/sources/shiboken2/ApiExtractor/include.cpp @@ -41,7 +41,7 @@ QString Include::toString() const return QLatin1String("import ") + m_name + QLatin1Char(';'); } -uint qHash(const Include& inc) +QtCompatHashFunctionType qHash(const Include& inc) { return qHash(inc.m_name); } @@ -49,7 +49,7 @@ uint qHash(const Include& inc) QTextStream& operator<<(QTextStream& out, const Include& include) { if (include.isValid()) - out << include.toString() << endl; + out << include.toString() << Qt::endl; return out; } diff --git a/sources/shiboken2/ApiExtractor/include.h b/sources/shiboken2/ApiExtractor/include.h index f7dfea5a7..2219fba55 100644 --- a/sources/shiboken2/ApiExtractor/include.h +++ b/sources/shiboken2/ApiExtractor/include.h @@ -29,6 +29,8 @@ #ifndef INCLUDE_H #define INCLUDE_H +#include <qtcompat.h> + #include <QString> #include <QVector> @@ -76,13 +78,13 @@ public: return m_type == other.m_type && m_name == other.m_name; } - friend uint qHash(const Include&); + friend QtCompatHashFunctionType qHash(const Include&); private: IncludeType m_type = IncludePath; QString m_name; }; -uint qHash(const Include& inc); +QtCompatHashFunctionType qHash(const Include& inc); QTextStream& operator<<(QTextStream& out, const Include& include); #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const Include &i); diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 0eb3c607f..0e905c9a0 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -28,6 +28,7 @@ #include "messages.h" #include "abstractmetalang.h" +#include "typedatabase.h" #include "typesystem.h" #include <codemodel.h> @@ -152,6 +153,22 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, return result; } +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te) +{ + QString result = QLatin1String("Ambiguous types found for \"") + qualifiedName + + QLatin1String("\": "); + QDebug(&result) << te; + return result; +} + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why) { @@ -218,6 +235,23 @@ QString msgCannotFindTypeEntry(const QString &t) return QLatin1String("Cannot find type entry for \"") + t + QLatin1String("\"."); } +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType) +{ + return QLatin1String("Cannot find type entry \"") + t + + QLatin1String("\" for instantiation of \"") + smartPointerType + QLatin1String("\"."); +} + +QString msgInvalidSmartPointerType(const TypeInfo &i) +{ + return QLatin1String("Invalid smart pointer type \"") + i.toString() + QLatin1String("\"."); +} + +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i) +{ + return QLatin1String("Cannot find instantiation of smart pointer type for \"") + + i.toString() + QLatin1String("\"."); +} + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why) @@ -356,8 +390,10 @@ QString msgCannotFindSmartPointer(const QString &instantiationType, QString result; QTextStream str(&result); str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; - for (auto t : pointers) - str << ' ' << t->fullName(); + for (auto t : pointers) { + auto typeEntry = t->typeEntry(); + str << ' ' << typeEntry->targetLangName() << '/' << typeEntry->qualifiedCppName(); + } str << ")."; return result; } diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index ad0553fbc..3934c35b3 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -66,6 +66,9 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, const TypeEntry *t); +QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); +QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); + QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, const QString &why); @@ -86,6 +89,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo, QString msgCannotFindTypeEntry(const QString &t); +QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType); +QString msgInvalidSmartPointerType(const TypeInfo &i); +QString msgCannotFindSmartPointerInstantion(const TypeInfo &i); + QString msgCannotTranslateTemplateArgument(int i, const TypeInfo &typeInfo, const QString &why); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index fdf2af872..e381ba083 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -40,7 +40,7 @@ #include <QtCore/QStack> // Predicate to find an item by name in a list of QSharedPointer<Item> -template <class T> class ModelItemNamePredicate : public std::unary_function<bool, QSharedPointer<T> > +template <class T> class ModelItemNamePredicate { public: explicit ModelItemNamePredicate(const QString &name) : m_name(name) {} @@ -91,6 +91,8 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope, return es; if (TypeDefModelItem tp = scope->findTypeDef(nameSegment)) return tp; + if (TemplateTypeAliasModelItem tta = scope->findTemplateTypeAlias(nameSegment)) + return tta; return CodeModelItem(); } if (auto nestedClass = scope->findClass(nameSegment)) @@ -191,13 +193,29 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con return resolveType(nextItem, combined, __scope); } + if (TemplateTypeAliasModelItem templateTypeAlias = qSharedPointerDynamicCast<_TemplateTypeAliasModelItem>(__item)) { + + TypeInfo combined = TypeInfo::combine(templateTypeAlias->type(), otherType); + // For the alias "template<typename T> using QList = QVector<T>" with + // other="QList<int>", replace the instantiations to obtain "QVector<int>". + auto aliasInstantiations = templateTypeAlias->type().instantiations(); + auto concreteInstantiations = otherType.instantiations(); + const int count = qMin(aliasInstantiations.size(), concreteInstantiations.size()); + for (int i = 0; i < count; ++i) + aliasInstantiations[i] = concreteInstantiations[i]; + combined.setInstantiations(aliasInstantiations); + const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); + if (!nextItem) + return combined; + return resolveType(nextItem, combined, __scope); + } + return otherType; } // Handler for clang::parseTemplateArgumentList() that populates // TypeInfo::m_instantiations -class TypeInfoTemplateArgumentHandler : - public std::binary_function<void, int, const QStringRef &> +class TypeInfoTemplateArgumentHandler { public: explicit TypeInfoTemplateArgumentHandler(TypeInfo *t) @@ -640,6 +658,9 @@ void _CodeModelItem::formatKind(QDebug &d, int k) case Kind_TypeDef: d << "TypeDefModelItem"; break; + case Kind_TemplateTypeAlias: + d << "TemplateTypeAliasModelItem"; + break; default: d << "CodeModelItem"; break; @@ -803,6 +824,11 @@ void _ScopeModelItem::addTypeDef(const TypeDefModelItem &item) m_typeDefs.append(item); } +void _ScopeModelItem::addTemplateTypeAlias(const TemplateTypeAliasModelItem &item) +{ + m_templateTypeAliases.append(item); +} + void _ScopeModelItem::addEnum(const EnumModelItem &item) { m_enums.append(item); @@ -813,6 +839,7 @@ void _ScopeModelItem::appendScope(const _ScopeModelItem &other) m_classes += other.m_classes; m_enums += other.m_enums; m_typeDefs += other.m_typeDefs; + m_templateTypeAliases += other.m_templateTypeAliases; m_variables += other.m_variables; m_functions += other.m_functions; m_enumsDeclarations += other.m_enumsDeclarations; @@ -857,6 +884,7 @@ void _ScopeModelItem::formatScopeItemsDebug(QDebug &d) const formatScopeList(d, ", classes=", m_classes, "\n", true); formatScopeList(d, ", enums=", m_enums, "\n", true); formatScopeList(d, ", aliases=", m_typeDefs, "\n", true); + formatScopeList(d, ", template type aliases=", m_templateTypeAliases, "\n", true); formatScopeList(d, ", functions=", m_functions, "\n", true); formatScopeList(d, ", variables=", m_variables); } @@ -872,7 +900,7 @@ namespace { // Predicate to match a non-template class name against the class list. // "Vector" should match "Vector" as well as "Vector<T>" (as seen for methods // from within the class "Vector"). -class ClassNamePredicate : public std::unary_function<bool, ClassModelItem> +class ClassNamePredicate { public: explicit ClassNamePredicate(const QString &name) : m_name(name) {} @@ -908,6 +936,11 @@ TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const return findModelItem(m_typeDefs, name); } +TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(const QString &name) const +{ + return findModelItem(m_templateTypeAliases, name); +} + EnumModelItem _ScopeModelItem::findEnum(const QString &name) const { return findModelItem(m_enums, name); @@ -950,6 +983,16 @@ void _NamespaceModelItem::appendNamespace(const _NamespaceModelItem &other) void _NamespaceModelItem::formatDebug(QDebug &d) const { _ScopeModelItem::formatDebug(d); + switch (m_type) { + case NamespaceType::Default: + break; + case NamespaceType::Anonymous: + d << ", anonymous"; + break; + case NamespaceType::Inline: + d << ", inline"; + break; + } formatScopeList(d, ", namespaces=", m_namespaces); } #endif // !QT_NO_DEBUG_STREAM @@ -1217,6 +1260,48 @@ void _TypeDefModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- + +_TemplateTypeAliasModelItem::_TemplateTypeAliasModelItem(CodeModel *model, int kind) + : _CodeModelItem(model, kind) {} + +_TemplateTypeAliasModelItem::_TemplateTypeAliasModelItem(CodeModel *model, const QString &name, int kind) + : _CodeModelItem(model, name, kind) {} + +TemplateParameterList _TemplateTypeAliasModelItem::templateParameters() const +{ + return m_templateParameters; +} + +void _TemplateTypeAliasModelItem::addTemplateParameter(const TemplateParameterModelItem &templateParameter) +{ + m_templateParameters.append(templateParameter); +} + +TypeInfo _TemplateTypeAliasModelItem::type() const +{ + return m_type; +} + +void _TemplateTypeAliasModelItem::setType(const TypeInfo &type) +{ + m_type = type; +} + +#ifndef QT_NO_DEBUG_STREAM +void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + d << ", <"; + for (int i = 0, count = m_templateParameters.size(); i < count; ++i) { + if (i) + d << ", "; + d << m_templateParameters.at(i)->name(); + } + d << ">, type=" << m_type; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- CodeModel::AccessPolicy _EnumModelItem::accessPolicy() const { return m_accessPolicy; @@ -1464,4 +1549,3 @@ void _MemberModelItem::formatDebug(QDebug &d) const #endif // !QT_NO_DEBUG_STREAM // kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 57b393f91..5bbd9ed3e 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -267,7 +267,8 @@ public: Kind_File = 5 << FirstKind | Kind_Namespace, Kind_TemplateParameter = 7 << FirstKind, Kind_TypeDef = 8 << FirstKind, - Kind_Variable = 9 << FirstKind | Kind_Member + Kind_TemplateTypeAlias = 9 << FirstKind, + Kind_Variable = 10 << FirstKind | Kind_Member }; public: @@ -333,18 +334,21 @@ public: EnumList enums() const { return m_enums; } inline FunctionList functions() const { return m_functions; } TypeDefList typeDefs() const { return m_typeDefs; } + TemplateTypeAliasList templateTypeAliases() const { return m_templateTypeAliases; } VariableList variables() const { return m_variables; } void addClass(const ClassModelItem &item); void addEnum(const EnumModelItem &item); void addFunction(const FunctionModelItem &item); void addTypeDef(const TypeDefModelItem &item); + void addTemplateTypeAlias(const TemplateTypeAliasModelItem &item); void addVariable(const VariableModelItem &item); ClassModelItem findClass(const QString &name) const; EnumModelItem findEnum(const QString &name) const; FunctionList findFunctions(const QString &name) const; TypeDefModelItem findTypeDef(const QString &name) const; + TemplateTypeAliasModelItem findTemplateTypeAlias(const QString &name) const; VariableModelItem findVariable(const QString &name) const; void addEnumsDeclaration(const QString &enumsDeclaration); @@ -372,6 +376,7 @@ private: ClassList m_classes; EnumList m_enums; TypeDefList m_typeDefs; + TemplateTypeAliasList m_templateTypeAliases; VariableList m_variables; FunctionList m_functions; @@ -440,6 +445,9 @@ public: const NamespaceList &namespaces() const { return m_namespaces; } + NamespaceType type() const { return m_type; } + void setType(NamespaceType t) { m_type = t; } + void addNamespace(NamespaceModelItem item); NamespaceModelItem findNamespace(const QString &name) const; @@ -452,6 +460,7 @@ public: private: NamespaceList m_namespaces; + NamespaceType m_type = NamespaceType::Default; }; class _FileModelItem: public _NamespaceModelItem @@ -679,6 +688,30 @@ private: TypeInfo m_type; }; +class _TemplateTypeAliasModelItem : public _CodeModelItem +{ +public: + DECLARE_MODEL_NODE(TemplateTypeAlias) + + explicit _TemplateTypeAliasModelItem(CodeModel *model, int kind = __node_kind); + explicit _TemplateTypeAliasModelItem(CodeModel *model, const QString &name, + int kind = __node_kind); + + TemplateParameterList templateParameters() const; + void addTemplateParameter(const TemplateParameterModelItem &templateParameter); + + TypeInfo type() const; + void setType(const TypeInfo &type); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + TemplateParameterList m_templateParameters; + TypeInfo m_type; +}; + class _EnumModelItem: public _CodeModelItem { public: diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index 1713ba42f..aebd59879 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -54,4 +54,11 @@ enum class ExceptionSpecification Throws }; +enum class NamespaceType +{ + Default, + Anonymous, + Inline +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h index 54dbe78dc..87fea5cde 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h @@ -47,6 +47,7 @@ class _NamespaceModelItem; class _ScopeModelItem; class _TemplateParameterModelItem; class _TypeDefModelItem; +class _TemplateTypeAliasModelItem; class _VariableModelItem; class _MemberModelItem; class TypeInfo; @@ -62,6 +63,7 @@ using NamespaceModelItem = QSharedPointer<_NamespaceModelItem>; using ScopeModelItem = QSharedPointer<_ScopeModelItem>; using TemplateParameterModelItem = QSharedPointer<_TemplateParameterModelItem>; using TypeDefModelItem = QSharedPointer<_TypeDefModelItem>; +using TemplateTypeAliasModelItem = QSharedPointer<_TemplateTypeAliasModelItem>; using VariableModelItem = QSharedPointer<_VariableModelItem>; using MemberModelItem = QSharedPointer<_MemberModelItem>; @@ -76,6 +78,7 @@ using NamespaceList = QVector<NamespaceModelItem>; using ScopeList = QVector<ScopeModelItem>; using TemplateParameterList = QVector<TemplateParameterModelItem>; using TypeDefList = QVector<TypeDefModelItem>; +using TemplateTypeAliasList = QVector<TemplateTypeAliasModelItem>; using VariableList = QVector<VariableModelItem>; using MemberList = QVector<MemberModelItem>; diff --git a/sources/shiboken2/ApiExtractor/qtcompat.h b/sources/shiboken2/ApiExtractor/qtcompat.h new file mode 100644 index 000000000..89a1db008 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/qtcompat.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCOMPAT_H +#define QTCOMPAT_H + +#include <QtCore/QtGlobal> + +#if QT_VERSION >= 0x060000 +using QtCompatHashFunctionType = size_t; +#else +using QtCompatHashFunctionType = uint; +#endif + +#endif // QTCOMPAT_H diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp index 2e50470e4..512473131 100644 --- a/sources/shiboken2/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp @@ -225,7 +225,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) if (!sourceFile.exists()) sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml")); if (!sourceFile.exists()) { - qCWarning(lcShiboken).noquote().nospace() + qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find qdoc file for class " << metaClass->name() << ", tried: " << QDir::toNativeSeparators(sourceFile.absoluteFilePath()); return; @@ -235,7 +235,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) QString errorMessage; XQueryPtr xquery = XQuery::create(sourceFileName, &errorMessage); if (xquery.isNull()) { - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } @@ -258,7 +258,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) Documentation doc(getDocumentation(xquery, query, classModifs)); if (doc.isEmpty()) - qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); metaClass->setDocumentation(doc); //Functions Documentation @@ -268,7 +268,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) queryFunctionDocumentation(sourceFileName, metaClass, classQuery, func, signedModifs, xquery, &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken(), "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); func->setDocumentation(Documentation(documentation)); } #if 0 @@ -291,7 +291,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) << meta_enum->name() << "\"]/description"; doc.setValue(getDocumentation(xquery, query, DocModificationList())); if (doc.isEmpty()) { - qCWarning(lcShiboken(), "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, query))); } meta_enum->setDocumentation(doc); @@ -321,7 +321,7 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) if (!QFile::exists(sourceFile)) sourceFile = prefix + QLatin1String("-module.webxml"); if (!QFile::exists(sourceFile)) { - qCWarning(lcShiboken).noquote().nospace() + qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find qdoc file for module " << name << ", tried: " << QDir::toNativeSeparators(sourceFile); return Documentation(); @@ -330,7 +330,7 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) QString errorMessage; XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage); if (xquery.isNull()) { - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return {}; } @@ -339,7 +339,7 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) + moduleName + QLatin1String("\"]/description"); Documentation doc = getDocumentation(xquery, query, DocModificationList()); if (doc.isEmpty()) { - qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(sourceFile, "module", name, query))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFile, "module", name, query))); return doc; } diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp index ee70a8e9b..a489f7548 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -35,7 +35,7 @@ #include <cstdarg> #include <cstdio> -#if _WINDOWS || NOCOLOR +#if defined(_WINDOWS) || defined(NOCOLOR) #define COLOR_END "" #define COLOR_WHITE "" #define COLOR_YELLOW "" @@ -58,6 +58,7 @@ static int m_step_warning = 0; static QElapsedTimer m_timer; Q_LOGGING_CATEGORY(lcShiboken, "qt.shiboken") +Q_LOGGING_CATEGORY(lcShibokenDoc, "qt.shiboken.doc") void ReportHandler::install() { @@ -80,6 +81,20 @@ void ReportHandler::setDebugLevel(ReportHandler::DebugLevel level) m_debugLevel = level; } +bool ReportHandler::setDebugLevelFromArg(const QString &level) +{ + bool result = true; + if (level == QLatin1String("sparse")) + ReportHandler::setDebugLevel(ReportHandler::SparseDebug); + else if (level == QLatin1String("medium")) + ReportHandler::setDebugLevel(ReportHandler::MediumDebug); + else if (level == QLatin1String("full")) + ReportHandler::setDebugLevel(ReportHandler::FullDebug); + else + result = false; + return result; +} + int ReportHandler::suppressedCount() { return m_suppressedCount; diff --git a/sources/shiboken2/ApiExtractor/reporthandler.h b/sources/shiboken2/ApiExtractor/reporthandler.h index 073586055..21f0e8933 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.h +++ b/sources/shiboken2/ApiExtractor/reporthandler.h @@ -33,6 +33,7 @@ #include <QString> Q_DECLARE_LOGGING_CATEGORY(lcShiboken) +Q_DECLARE_LOGGING_CATEGORY(lcShibokenDoc) class ReportHandler { @@ -44,6 +45,7 @@ public: static DebugLevel debugLevel(); static void setDebugLevel(DebugLevel level); + static bool setDebugLevelFromArg(const QString &); static int warningCount(); diff --git a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt index a36cc17de..97ae0f850 100644 --- a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt @@ -15,7 +15,7 @@ macro(declare_test testname) ${CMAKE_CURRENT_BINARY_DIR} ${apiextractor_SOURCE_DIR} ) - target_link_libraries(${testname} PRIVATE apiextractor Qt5::Test) + target_link_libraries(${testname} PRIVATE apiextractor Qt${QT_MAJOR_VERSION}::Test) add_test(${testname} ${testname}) if (INSTALL_TESTS) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname} diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp index f2e15fdb0..f0aa4a318 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp @@ -588,4 +588,34 @@ void TestAbstractMetaClass::testIsPolymorphic() QVERIFY(!a->isPolymorphic()); } +void TestAbstractMetaClass::testClassTypedefedBaseClass() +{ + const char cppCode[] =R"CPP( +class Base { +}; + +using BaseAlias1 = Base; +using BaseAlias2 = BaseAlias1; + +class Derived : public BaseAlias2 { +}; +)CPP"; + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <object-type name='Base'/> + <object-type name='Derived'/> +</typesystem> +)XML"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + auto base = AbstractMetaClass::findClass(classes, QLatin1String("Base")); + QVERIFY(base); + auto derived = AbstractMetaClass::findClass(classes, QLatin1String("Derived")); + QVERIFY(derived); + QCOMPARE(derived->baseClasses().value(0), base); +} + QTEST_APPLESS_MAIN(TestAbstractMetaClass) diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h index e19973625..1d9f8d8f6 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h @@ -51,6 +51,7 @@ private slots: void testAbstractClassDefaultConstructors(); void testObjectTypesMustNotHaveCopyConstructors(); void testIsPolymorphic(); + void testClassTypedefedBaseClass(); }; #endif // TESTABSTRACTMETACLASS_H diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp index c50084b8e..ca4af9a10 100644 --- a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -283,7 +283,7 @@ void TestAddFunction::testAddFunctionAtModuleLevel() QCOMPARE(mods.size(), 1); QVERIFY(mods.first().isCodeInjection()); CodeSnip snip = mods.first().snips.first(); - QCOMPARE(snip.code(), QLatin1String("custom_code();")); + QCOMPARE(snip.code().trimmed(), QLatin1String("custom_code();")); } void TestAddFunction::testAddFunctionWithVarargs() diff --git a/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp index 2234fb4c3..aaa72238c 100644 --- a/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp @@ -57,8 +57,10 @@ void TestContainer::testContainerType() //search for class A AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); QVERIFY(classA); - QVERIFY(classA->typeEntry()->baseContainerType()); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(classA->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::ListContainer); + auto baseContainer = classA->typeEntry()->baseContainerType(); + QVERIFY(baseContainer); + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(), + ContainerTypeEntry::ListContainer); } void TestContainer::testListOfValueType() diff --git a/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp index 10194eb34..e61418467 100644 --- a/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp @@ -69,7 +69,7 @@ void TestNestedTypes::testNestedTypesModifications() QCOMPARE(ins->functions().count(), 1); QCOMPARE(ins->typeEntry()->codeSnips().count(), 1); CodeSnip snip = ins->typeEntry()->codeSnips().first(); - QCOMPARE(snip.code(), QLatin1String("custom_code1();")); + QCOMPARE(snip.code().trimmed(), QLatin1String("custom_code1();")); AbstractMetaFunction* addedFunc = ins->functions().first(); QVERIFY(addedFunc->isUserAdded()); @@ -80,7 +80,7 @@ void TestNestedTypes::testNestedTypesModifications() QCOMPARE(addedFunc->modifications().size(), 1); QVERIFY(addedFunc->modifications().first().isCodeInjection()); snip = addedFunc->modifications().first().snips.first(); - QCOMPARE(snip.code(), QLatin1String("custom_code2();")); + QCOMPARE(snip.code().trimmed(), QLatin1String("custom_code2();")); const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); QVERIFY(ins); diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp index 5191cb38d..ec3ddb8b2 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp @@ -428,8 +428,10 @@ typedef Vector<int> IntVector; AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, QLatin1String("IntVector")); QVERIFY(vector); - QVERIFY(vector->typeEntry()->baseContainerType()); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(vector->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::VectorContainer); + auto baseContainer = vector->typeEntry()->baseContainerType(); + QVERIFY(baseContainer); + QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(), + ContainerTypeEntry::VectorContainer); QCOMPARE(vector->functions().count(), 4); const AbstractMetaFunction* method = vector->findFunction(QLatin1String("method")); @@ -443,6 +445,35 @@ typedef Vector<int> IntVector; QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector<int >")); } +void TestTemplates::testNonTypeTemplates() +{ + // PYSIDe-1296, functions with non type templates parameters. + const char cppCode[] = R"CPP( +template <class T, int Size> +class Array { + T array[Size]; +}; + +Array<int, 2> foo(); + +)CPP"; + + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <primitive-type name='int'/> + <container-type name='Array' type='vector'/> + <function signature="foo()"/> +</typesystem>)XML"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); + QVERIFY(!builder.isNull()); + auto functions = builder->globalFunctions(); + QCOMPARE(functions.count(), 1); + auto foo = functions.constFirst(); + QCOMPARE(foo->name(), QLatin1String("foo")); + QCOMPARE(foo->type()->name(), QLatin1String("Array")); +} + // Perform checks on template inheritance; a typedef of a template class // should result in rewritten types. void TestTemplates::testTemplateTypeDefs_data() @@ -561,4 +592,53 @@ void TestTemplates::testTemplateTypeDefs() QCOMPARE(xmlValueField->type()->cppSignature(), QLatin1String("int")); } +void TestTemplates::testTemplateTypeAliases() +{ + // Model Qt 6's "template<typename T> using QList = QVector<T>" + const char cppCode[] = R"CPP( +template<typename T> +class Container1 { }; + +template<typename T> +using Container2 = Container1<T>; + +class Test +{ +public: + Container2<int> m_intContainer; +}; + +class Derived : public Container2<int> +{ +public: +}; +)CPP"; + + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <primitive-type name='int'/> + <value-type name='Container1'/> + <value-type name='Derived'/> + <object-type name='Test'/> +</typesystem>)XML"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + auto testClass = AbstractMetaClass::findClass(classes, QLatin1String("Test")); + QVERIFY(testClass); + + auto fields = testClass->fields(); + QCOMPARE(fields.count(), 1); + auto fieldType = testClass->fields().at(0)->type(); + QCOMPARE(fieldType->name(), QLatin1String("Container1")); + QCOMPARE(fieldType->instantiations().size(), 1); + + auto derived = AbstractMetaClass::findClass(classes, QLatin1String("Derived")); + QVERIFY(derived); + auto base = derived->templateBaseClass(); + QCOMPARE(base->name(), QLatin1String("Container1")); +} + QTEST_APPLESS_MAIN(TestTemplates) diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.h b/sources/shiboken2/ApiExtractor/tests/testtemplates.h index df3de18b9..c96e7fe4a 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.h +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.h @@ -46,8 +46,10 @@ private slots: void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); void testTypedefOfInstantiationOfTemplateClass(); void testContainerTypeIncompleteArgument(); + void testNonTypeTemplates(); void testTemplateTypeDefs_data(); void testTemplateTypeDefs(); + void testTemplateTypeAliases(); }; #endif diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index f393bf3bf..4a29a25c9 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -144,6 +144,25 @@ IncludeList TypeDatabase::extraIncludes(const QString& className) const return typeEntry ? typeEntry->extraIncludes() : IncludeList(); } +void TypeDatabase::addSystemInclude(const QString &name) +{ + m_systemIncludes.append(name.toUtf8()); +} + +// Add a lookup for the short name excluding inline namespaces +// so that "std::shared_ptr" finds "std::__1::shared_ptr" as well. +// Note: This inserts duplicate TypeEntry * into m_entries. +void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n) +{ + QVector<TypeEntry *> additionalEntries; // Store before modifying the hash + for (TypeEntry *entry : m_entries) { + if (entry->isChildOf(n)) + additionalEntries.append(entry); + } + for (const auto &ae : additionalEntries) + m_entries.insert(ae->shortName(), ae); +} + ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; @@ -166,7 +185,7 @@ static bool inline useType(const TypeEntry *t) FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->type() == TypeEntry::FunctionType && useType(entry)) return static_cast<FunctionTypeEntry*>(entry); @@ -201,7 +220,7 @@ QString TypeDatabase::defaultPackageName() const TypeEntry* TypeDatabase::findType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (useType(entry)) return entry; @@ -209,7 +228,53 @@ TypeEntry* TypeDatabase::findType(const QString& name) const return nullptr; } -TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypes(const QString &name) const +template <class Predicate> +TypeEntries TypeDatabase::findTypesHelper(const QString &name, Predicate pred) const +{ + TypeEntries result; + const auto entries = findTypeRange(name); + for (TypeEntry *entry : entries) { + if (pred(entry)) + result.append(entry); + } + return result; +} + +TypeEntries TypeDatabase::findTypes(const QString &name) const +{ + return findTypesHelper(name, useType); +} + +static bool useCppType(const TypeEntry *t) +{ + bool result = false; + switch (t->type()) { + case TypeEntry::PrimitiveType: + case TypeEntry::VoidType: + case TypeEntry::FlagsType: + case TypeEntry::EnumType: + case TypeEntry::TemplateArgumentType: + case TypeEntry::BasicValueType: + case TypeEntry::ContainerType: + case TypeEntry::ObjectType: + case TypeEntry::ArrayType: + case TypeEntry::CustomType: + case TypeEntry::SmartPointerType: + case TypeEntry::TypedefType: + result = useType(t); + break; + default: + break; + } + return result; +} + +TypeEntries TypeDatabase::findCppTypes(const QString &name) const +{ + return findTypesHelper(name, useCppType); +} + +TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypeRange(const QString &name) const { const auto range = m_entries.equal_range(name); return {range.first, range.second}; @@ -322,11 +387,10 @@ TypeEntry *TypeDatabase::resolveTypeDefEntry(TypedefEntry *typedefEntry, if (lessThanPos != -1) sourceName.truncate(lessThanPos); ComplexTypeEntry *source = nullptr; - for (TypeEntry *e : findTypes(sourceName)) { + for (TypeEntry *e : findTypeRange(sourceName)) { switch (e->type()) { case TypeEntry::BasicValueType: case TypeEntry::ContainerType: - case TypeEntry::InterfaceType: case TypeEntry::ObjectType: case TypeEntry::SmartPointerType: source = dynamic_cast<ComplexTypeEntry *>(e); @@ -362,6 +426,17 @@ bool TypeDatabase::addType(TypeEntry *e, QString *errorMessage) return true; } +// Add a dummy value entry for non-type template parameters +ConstantValueTypeEntry * + TypeDatabase::addConstantValueTypeEntry(const QString &value, + const TypeEntry *parent) +{ + auto result = new ConstantValueTypeEntry(value, parent); + result->setCodeGeneration(0); + addType(result); + return result; +} + bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, QString *reason) const { @@ -557,15 +632,8 @@ bool TypeDatabase::parseFile(const QString &filename, const QString ¤tPath return false; } - int count = m_entries.size(); bool ok = parseFile(&file, generate); m_parsedTypesystemFiles[filepath] = ok; - int newCount = m_entries.size(); - - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("Parsed: '%1', %2 new entries").arg(filename).arg(newCount - count); - } return ok; } @@ -581,7 +649,7 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isPrimitive()) { auto *pe = static_cast<PrimitiveTypeEntry *>(entry); @@ -595,7 +663,7 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isComplex() && useType(entry)) return static_cast<ComplexTypeEntry*>(entry); @@ -605,7 +673,7 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry && entry->isObject() && useType(entry)) return static_cast<ObjectTypeEntry*>(entry); @@ -616,7 +684,7 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) const { NamespaceTypeEntryList result; - const auto entries = findTypes(name); + const auto entries = findTypeRange(name); for (TypeEntry *entry : entries) { if (entry->isNamespace()) result.append(static_cast<NamespaceTypeEntry*>(entry)); @@ -698,6 +766,35 @@ static void _computeTypeIndexes() computeTypeIndexes = false; } +// Build the C++ name excluding any inline namespaces +// ("std::__1::shared_ptr" -> "std::shared_ptr" +QString TypeEntry::shortName() const +{ + if (m_cachedShortName.isEmpty()) { + QVarLengthArray<const TypeEntry *> parents; + bool foundInlineNamespace = false; + for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { + if (p->type() == TypeEntry::NamespaceType + && static_cast<const NamespaceTypeEntry *>(p)->isInlineNamespace()) { + foundInlineNamespace = true; + } else { + parents.append(p); + } + } + if (foundInlineNamespace) { + m_cachedShortName.reserve(m_name.size()); + for (int i = parents.size() - 1; i >= 0; --i) { + m_cachedShortName.append(parents.at(i)->entryName()); + m_cachedShortName.append(QLatin1String("::")); + } + m_cachedShortName.append(m_entryName); + } else { + m_cachedShortName = m_name; + } + } + return m_cachedShortName; +} + void TypeEntry::setRevision(int r) { if (m_revision != r) { @@ -794,7 +891,7 @@ void TypeEntry::formatDebug(QDebug &d) const if (m_name != cppName) d << "\", cppName=\"" << cppName << '"'; d << ", type=" << m_type << ", codeGeneration=0x" - << hex << m_codeGeneration << dec + << Qt::hex << m_codeGeneration << Qt::dec << ", target=\"" << targetLangName() << '"'; FORMAT_NONEMPTY_STRING("package", m_targetLangPackage) FORMAT_BOOL("stream", m_stream) @@ -849,12 +946,26 @@ void NamespaceTypeEntry::formatDebug(QDebug &d) const ComplexTypeEntry::formatDebug(d); auto pattern = m_filePattern.pattern(); FORMAT_NONEMPTY_STRING("pattern", pattern) + d << ",visibility=" << m_visibility; + if (m_inlineNamespace) + d << "[inline]"; } void ContainerTypeEntry::formatDebug(QDebug &d) const { ComplexTypeEntry::formatDebug(d); - d << ", type=" << m_type << ",\"" << typeName() << '"'; + d << ", type=" << m_containerKind << ",\"" << typeName() << '"'; +} + +void SmartPointerTypeEntry::formatDebug(QDebug &d) const +{ + ComplexTypeEntry::formatDebug(d); + if (!m_instantiations.isEmpty()) { + d << ", instantiations[" << m_instantiations.size() << "]=("; + for (auto i : m_instantiations) + d << i->name() << ','; + d << ')'; + } } QDebug operator<<(QDebug d, const TypeEntry *te) diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index f615b623d..7651d6b7b 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -96,6 +96,11 @@ public: IncludeList extraIncludes(const QString &className) const; + const QByteArrayList &systemIncludes() const { return m_systemIncludes; } + void addSystemInclude(const QString &name); + + void addInlineNamespaceLookups(const NamespaceTypeEntry *n); + PrimitiveTypeEntry *findPrimitiveType(const QString &name) const; ComplexTypeEntry *findComplexType(const QString &name) const; ObjectTypeEntry *findObjectType(const QString &name) const; @@ -108,6 +113,8 @@ public: QString defaultPackageName() const; TypeEntry *findType(const QString &name) const; + TypeEntries findTypes(const QString &name) const; + TypeEntries findCppTypes(const QString &name) const; const TypeEntryMultiMap &entries() const { return m_entries; } const TypedefEntryMap &typedefEntries() const { return m_typedefEntries; } @@ -130,6 +137,8 @@ public: QString *reason = nullptr) const; bool addType(TypeEntry *e, QString *errorMessage = nullptr); + ConstantValueTypeEntry *addConstantValueTypeEntry(const QString &value, + const TypeEntry *parent); void addTypeSystemType(const TypeSystemTypeEntry *e); FlagsTypeEntry *findFlagsType(const QString &name) const; @@ -179,11 +188,13 @@ public: void formatDebug(QDebug &d) const; #endif private: - TypeEntryMultiMapConstIteratorRange findTypes(const QString &name) const; + TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; + template <class Predicate> + TypeEntries findTypesHelper(const QString &name, Predicate pred) const; TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); bool m_suppressWarnings = true; - TypeEntryMultiMap m_entries; + TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; @@ -201,6 +212,7 @@ private: QVector<TypeRejection> m_rejections; QStringList m_dropTypeEntries; + QByteArrayList m_systemIncludes; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h index 0bb5cde1d..f9e6c669e 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h @@ -33,6 +33,7 @@ #include <QtCore/QString> #include <QtCore/QVector> +class ConstantValueTypeEntry; class ContainerTypeEntry; class NamespaceTypeEntry; class PrimitiveTypeEntry; diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index abd2bfb07..729e6b32b 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -34,6 +34,7 @@ #include <QtCore/QSet> #include <algorithm> +#include <limits> static QString strings_Object = QLatin1String("Object"); static QString strings_String = QLatin1String("String"); @@ -144,7 +145,7 @@ ComplexTypeEntry::ComplexTypeEntry(const ComplexTypeEntry &) = default; QString ContainerTypeEntry::qualifiedCppName() const { - if (m_type == StringListContainer) + if (m_containerKind == StringListContainer) return QLatin1String("QStringList"); return ComplexTypeEntry::qualifiedCppName(); } @@ -212,7 +213,7 @@ QString TemplateInstance::expandCode() const if (!code.startsWith(QLatin1Char('\n'))) result += QLatin1Char('\n'); result += code; - result += QLatin1String("\n// TEMPLATE - ") + m_name + QLatin1String(" - END"); + result += QLatin1String("\n// TEMPLATE - ") + m_name + QLatin1String(" - END\n"); return result; } @@ -226,6 +227,82 @@ QString CodeSnipAbstract::code() const return res; } +void CodeSnipAbstract::addCode(const QString &code) +{ + codeList.append(CodeSnipFragment(fixSpaces(code))); +} + +template <class String> // QString, QStringRef +static inline int firstNonBlank(const String &s) +{ + const auto it = std::find_if(s.cbegin(), s.cend(), + [] (QChar c) { return !c.isSpace(); }); + return int(it - s.cbegin()); +} + +template <class String> // QString, QStringRef +static inline bool isEmpty(const String &s) +{ + return s.isEmpty() + || std::all_of(s.cbegin(), s.cend(), + [] (QChar c) { return c.isSpace(); }); +} + +QString CodeSnipAbstract::dedent(const QString &code) +{ + if (code.isEmpty()) + return code; + // Right trim if indent=0, or trim if single line + if (!code.at(0).isSpace() || !code.contains(QLatin1Char('\n'))) + return code.trimmed(); + const auto lines = code.splitRef(QLatin1Char('\n')); + int spacesToRemove = std::numeric_limits<int>::max(); + for (const auto &line : lines) { + if (!isEmpty(line)) { + const int nonSpacePos = firstNonBlank(line); + if (nonSpacePos < spacesToRemove) + spacesToRemove = nonSpacePos; + if (spacesToRemove == 0) + return code; + } + } + QString result; + for (const auto &line : lines) { + if (!isEmpty(line) && spacesToRemove < line.size()) + result += line.mid(spacesToRemove).toString(); + result += QLatin1Char('\n'); + } + return result; +} + +QString CodeSnipAbstract::fixSpaces(QString code) +{ + code.remove(QLatin1Char('\r')); + // Check for XML <tag>\n<space>bla... + if (code.startsWith(QLatin1String("\n "))) + code.remove(0, 1); + while (!code.isEmpty() && code.back().isSpace()) + code.chop(1); + code = dedent(code); + if (!code.isEmpty() && !code.endsWith(QLatin1Char('\n'))) + code.append(QLatin1Char('\n')); + return code; +} + +// Prepend a line to the code, observing indentation +void CodeSnipAbstract::prependCode(QString *code, QString firstLine) +{ + while (!code->isEmpty() && code->front() == QLatin1Char('\n')) + code->remove(0, 1); + if (!code->isEmpty() && code->front().isSpace()) { + const int indent = firstNonBlank(*code); + firstLine.prepend(QString(indent, QLatin1Char(' '))); + } + if (!firstLine.endsWith(QLatin1Char('\n'))) + firstLine += QLatin1Char('\n'); + code->prepend(firstLine); +} + QString CodeSnipFragment::code() const { return m_instance ? m_instance->expandCode() : m_code; @@ -433,7 +510,7 @@ QDebug operator<<(QDebug d, const CodeSnip &s) void Modification::formatDebug(QDebug &d) const { - d << "modifiers=" << hex << showbase << modifiers << noshowbase << dec; + d << "modifiers=" << Qt::hex << Qt::showbase << modifiers << Qt::noshowbase << Qt::dec; if (removal) d << ", removal"; if (!renamedToName.isEmpty()) @@ -595,7 +672,7 @@ QString ComplexTypeEntry::targetLangApiName() const QString ContainerTypeEntry::typeName() const { - switch(m_type) { + switch (m_containerKind) { case LinkedListContainer: return QLatin1String("linked-list"); case ListContainer: @@ -684,6 +761,15 @@ TypeEntry::~TypeEntry() delete m_customConversion; } +bool TypeEntry::isChildOf(const TypeEntry *p) const +{ + for (auto e = m_parent; e; e = e->parent()) { + if (e == p) + return true; + } + return false; +} + const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const { for (auto e = this; e; e = e->parent()) { @@ -693,6 +779,16 @@ const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const return nullptr; } +const TypeEntry *TypeEntry::targetLangEnclosingEntry() const +{ + auto result = m_parent; + while (result && result->type() != TypeEntry::TypeSystemType + && !NamespaceTypeEntry::isVisibleScope(result)) { + result = result->parent(); + } + return result; +} + QString TypeEntry::targetLangName() const { if (m_cachedTargetLangName.isEmpty()) @@ -704,11 +800,13 @@ QString TypeEntry::buildTargetLangName() const { QString result = m_entryName; for (auto p = parent(); p && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { - if (!result.isEmpty()) - result.prepend(QLatin1Char('.')); - QString n = p->m_entryName; - n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" - result.prepend(n); + if (NamespaceTypeEntry::isVisibleScope(p)) { + if (!result.isEmpty()) + result.prepend(QLatin1Char('.')); + QString n = p->m_entryName; + n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" + result.prepend(n); + } } return result; } @@ -752,6 +850,8 @@ TypeEntry *TypeEntry::clone() const // Take over parameters relevant for typedefs void TypeEntry::useAsTypedef(const TypeEntry *source) { + // XML Typedefs are in the global namespace for now. + m_parent = source->typeSystemTypeEntry(); m_entryName = source->m_entryName; m_name = source->m_name; m_targetLangPackage = source->m_targetLangPackage; @@ -905,11 +1005,11 @@ TypeEntry *TypedefEntry::clone() const TypedefEntry::TypedefEntry(const TypedefEntry &) = default; -ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, Type type, +ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, ContainerType, vr, parent), - m_type(type) + m_containerKind(containerKind) { setCodeGeneration(GenerateForSubclass); } @@ -933,6 +1033,11 @@ TypeEntry *SmartPointerTypeEntry::clone() const SmartPointerTypeEntry::SmartPointerTypeEntry(const SmartPointerTypeEntry &) = default; +bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntry *e) const +{ + return m_instantiations.isEmpty() || m_instantiations.contains(e); +} + NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, NamespaceType, vr, parent) @@ -959,6 +1064,18 @@ bool NamespaceTypeEntry::matchesFile(const QString &needle) const return m_filePattern.match(needle).hasMatch(); } +bool NamespaceTypeEntry::isVisible() const +{ + return m_visibility == TypeSystem::Visibility::Visible + || (m_visibility == TypeSystem::Visibility::Auto && !m_inlineNamespace); +} + +bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e) +{ + return e->type() != TypeEntry::NamespaceType + || static_cast<const NamespaceTypeEntry *>(e)->isVisible(); +} + ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : ComplexTypeEntry(entryName, BasicValueType, vr, parent) @@ -970,11 +1087,6 @@ bool ValueTypeEntry::isValue() const return true; } -bool ValueTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ValueTypeEntry::clone() const { return new ValueTypeEntry(*this); @@ -1122,30 +1234,6 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent) : - ComplexTypeEntry(entryName, InterfaceType, vr, parent) -{ -} - -bool InterfaceTypeEntry::isNativeIdBased() const -{ - return true; -} - -QString InterfaceTypeEntry::qualifiedCppName() const -{ - const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); - return ComplexTypeEntry::qualifiedCppName().left(len); -} - -TypeEntry *InterfaceTypeEntry::clone() const -{ - return new InterfaceTypeEntry(*this); -} - -InterfaceTypeEntry::InterfaceTypeEntry(const InterfaceTypeEntry &) = default; - FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, const QVersionNumber &vr, const TypeEntry *parent) : @@ -1167,19 +1255,14 @@ ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber { } -InterfaceTypeEntry *ObjectTypeEntry::designatedInterface() const -{ - return m_interface; -} - -bool ObjectTypeEntry::isNativeIdBased() const -{ - return true; -} - TypeEntry *ObjectTypeEntry::clone() const { return new ObjectTypeEntry(*this); } ObjectTypeEntry::ObjectTypeEntry(const ObjectTypeEntry &) = default; + +void DocModification::setCode(const QString &code) +{ + m_code = CodeSnipAbstract::fixSpaces(code); +} diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 4d0a23ca1..c6995b64d 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -115,7 +115,7 @@ class CodeSnipAbstract public: QString code() const; - void addCode(const QString &code) { codeList.append(CodeSnipFragment(code)); } + void addCode(const QString &code); void addCode(const QStringRef &code) { addCode(code.toString()); } void addTemplateInstance(TemplateInstance *ti) @@ -124,6 +124,10 @@ public: } QVector<CodeSnipFragment> codeList; + + static QString fixSpaces(QString code); + static QString dedent(const QString &code); + static void prependCode(QString *code, QString firstLine); }; class CustomFunction : public CodeSnipAbstract @@ -228,7 +232,7 @@ struct ArgumentModification struct Modification { - enum Modifiers { + enum Modifiers : uint { InvalidModifier = 0x0000, Private = 0x0001, Protected = 0x0002, @@ -499,7 +503,6 @@ QDebug operator<<(QDebug d, const AddedFunction::Argument &a); QDebug operator<<(QDebug d, const AddedFunction &af); #endif -class InterfaceTypeEntry; class ObjectTypeEntry; class DocModification @@ -511,8 +514,8 @@ public: explicit DocModification(TypeSystem::DocModificationMode mode, const QString& signature) : m_signature(signature), m_mode(mode) {} - void setCode(const QString& code) { m_code = code; } - void setCode(const QStringRef& code) { m_code = code.toString(); } + void setCode(const QString& code); + void setCode(const QStringRef& code) { setCode(code.toString()); } QString code() const { @@ -562,20 +565,13 @@ public: EnumValue, ConstantValueType, TemplateArgumentType, - ThreadType, BasicValueType, - StringType, ContainerType, - InterfaceType, ObjectType, NamespaceType, - VariantType, - JObjectWrapperType, - CharType, ArrayType, TypeSystemType, CustomType, - TargetLangType, FunctionType, SmartPointerType, TypedefType @@ -605,7 +601,10 @@ public: const TypeEntry *parent() const { return m_parent; } void setParent(const TypeEntry *p) { m_parent = p; } + bool isChildOf(const TypeEntry *p) const; const TypeSystemTypeEntry *typeSystemTypeEntry() const; + // cf AbstractMetaClass::targetLangEnclosingClass() + const TypeEntry *targetLangEnclosingEntry() const; bool isPrimitive() const { @@ -619,22 +618,10 @@ public: { return m_type == FlagsType; } - bool isInterface() const - { - return m_type == InterfaceType; - } bool isObject() const { return m_type == ObjectType; } - bool isString() const - { - return m_type == StringType; - } - bool isChar() const - { - return m_type == CharType; - } bool isNamespace() const { return m_type == NamespaceType; @@ -647,14 +634,6 @@ public: { return m_type == SmartPointerType; } - bool isVariant() const - { - return m_type == VariantType; - } - bool isJObjectWrapper() const - { - return m_type == JObjectWrapperType; - } bool isArray() const { return m_type == ArrayType; @@ -671,18 +650,10 @@ public: { return m_type == VarargsType; } - bool isThread() const - { - return m_type == ThreadType; - } bool isCustom() const { return m_type == CustomType; } - bool isBasicValue() const - { - return m_type == BasicValueType; - } bool isTypeSystem() const { return m_type == TypeSystemType; @@ -708,6 +679,8 @@ public: // The type's name in C++, fully qualified QString name() const { return m_name; } + // C++ excluding inline namespaces + QString shortName() const; // Name as specified in XML QString entryName() const { return m_entryName; } @@ -766,11 +739,6 @@ public: QString qualifiedTargetLangName() const; - virtual InterfaceTypeEntry *designatedInterface() const - { - return nullptr; - } - void setCustomConstructor(const CustomFunction &func) { m_customConstructor = func; @@ -798,11 +766,6 @@ public: return false; } - virtual bool isNativeIdBased() const - { - return false; - } - CodeSnipList codeSnips() const; void setCodeSnips(const CodeSnipList &codeSnips) { @@ -896,7 +859,8 @@ protected: private: const TypeEntry *m_parent; - QString m_name; // fully qualified + QString m_name; // C++ fully qualified + mutable QString m_cachedShortName; // C++ excluding inline namespaces QString m_entryName; QString m_targetLangPackage; mutable QString m_cachedTargetLangName; // "Foo.Bar" @@ -1446,7 +1410,7 @@ class ContainerTypeEntry : public ComplexTypeEntry { Q_GADGET public: - enum Type { + enum ContainerKind { NoContainer, ListContainer, StringListContainer, @@ -1461,14 +1425,14 @@ public: MultiHashContainer, PairContainer, }; - Q_ENUM(Type) + Q_ENUM(ContainerKind) - explicit ContainerTypeEntry(const QString &entryName, Type type, const QVersionNumber &vr, - const TypeEntry *parent); + explicit ContainerTypeEntry(const QString &entryName, ContainerKind containerKind, + const QVersionNumber &vr, const TypeEntry *parent); - Type type() const + ContainerKind containerKind() const { - return m_type; + return m_containerKind; } QString typeName() const; @@ -1483,12 +1447,14 @@ protected: ContainerTypeEntry(const ContainerTypeEntry &); private: - Type m_type; + ContainerKind m_containerKind; }; class SmartPointerTypeEntry : public ComplexTypeEntry { public: + using Instantiations = QVector<const TypeEntry *>; + explicit SmartPointerTypeEntry(const QString &entryName, const QString &getterName, const QString &smartPointerType, @@ -1508,6 +1474,13 @@ public: TypeEntry *clone() const override; + Instantiations instantiations() const { return m_instantiations; } + void setInstantiations(const Instantiations &i) { m_instantiations = i; } + bool matchesInstantiation(const TypeEntry *e) const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif protected: SmartPointerTypeEntry(const SmartPointerTypeEntry &); @@ -1515,6 +1488,7 @@ private: QString m_getterName; QString m_smartPointerType; QString m_refCountMethodName; + Instantiations m_instantiations; }; class NamespaceTypeEntry : public ComplexTypeEntry @@ -1535,6 +1509,15 @@ public: bool matchesFile(const QString &needle) const; + bool isVisible() const; + void setVisibility(TypeSystem::Visibility v) { m_visibility = v; } + + // C++ 11 inline namespace, from code model + bool isInlineNamespace() const { return m_inlineNamespace; } + void setInlineNamespace(bool i) { m_inlineNamespace = i; } + + static bool isVisibleScope(const TypeEntry *e); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -1545,7 +1528,9 @@ protected: private: QRegularExpression m_filePattern; const NamespaceTypeEntry *m_extends = nullptr; + TypeSystem::Visibility m_visibility = TypeSystem::Visibility::Auto; bool m_hasPattern = false; + bool m_inlineNamespace = false; }; class ValueTypeEntry : public ComplexTypeEntry @@ -1556,8 +1541,6 @@ public: bool isValue() const override; - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: @@ -1566,39 +1549,6 @@ protected: ValueTypeEntry(const ValueTypeEntry &); }; -class InterfaceTypeEntry : public ComplexTypeEntry -{ -public: - explicit InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, - const TypeEntry *parent); - - static QString interfaceName(const QString &name) - { - return name + QLatin1String("Interface"); - } - - ObjectTypeEntry *origin() const - { - return m_origin; - } - void setOrigin(ObjectTypeEntry *origin) - { - m_origin = origin; - } - - bool isNativeIdBased() const override; - QString qualifiedCppName() const override; - - TypeEntry *clone() const override; - -protected: - InterfaceTypeEntry(const InterfaceTypeEntry &); - -private: - ObjectTypeEntry *m_origin = nullptr; -}; - - class FunctionTypeEntry : public TypeEntry { public: @@ -1635,21 +1585,10 @@ public: explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - InterfaceTypeEntry *designatedInterface() const override; - void setDesignatedInterface(InterfaceTypeEntry *entry) - { - m_interface = entry; - } - - bool isNativeIdBased() const override; - TypeEntry *clone() const override; protected: ObjectTypeEntry(const ObjectTypeEntry &); - -private: - InterfaceTypeEntry *m_interface = nullptr; }; struct TypeRejection diff --git a/sources/shiboken2/ApiExtractor/typesystem_enums.h b/sources/shiboken2/ApiExtractor/typesystem_enums.h index df83429d0..120c9417f 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_enums.h +++ b/sources/shiboken2/ApiExtractor/typesystem_enums.h @@ -98,6 +98,13 @@ enum class ExceptionHandling { On }; +enum Visibility { // For namespaces + Unspecified, + Visible, + Invisible, + Auto +}; + } // namespace TypeSystem #endif // TYPESYSTEM_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h index fd702793e..73f92b294 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -40,6 +40,7 @@ class DocModification; struct AddedFunction; struct FieldModification; struct FunctionModification; +class TypeEntry; using AddedFunctionPtr = QSharedPointer<AddedFunction>; using AddedFunctionList = QVector<AddedFunctionPtr>; @@ -47,5 +48,6 @@ using CodeSnipList = QVector<CodeSnip>; using DocModificationList = QVector<DocModification>; using FieldModificationList = QVector<FieldModification>; using FunctionModificationList = QVector<FunctionModification>; +using TypeEntries = QVector<const TypeEntry *>; #endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 98c729a32..0ba94d94e 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -62,6 +62,7 @@ static inline QString deleteInMainThreadAttribute() { return QStringLiteral("del static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); } static inline QString exceptionHandlingAttribute() { return QStringLiteral("exception-handling"); } static inline QString extensibleAttribute() { return QStringLiteral("extensible"); } +static inline QString fileNameAttribute() { return QStringLiteral("file-name"); } static inline QString flagsAttribute() { return QStringLiteral("flags"); } static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); } static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); } @@ -94,6 +95,7 @@ static inline QString sourceAttribute() { return QStringLiteral("source"); } static inline QString streamAttribute() { return QStringLiteral("stream"); } static inline QString xPathAttribute() { return QStringLiteral("xpath"); } static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); } +static inline QString visibleAttribute() { return QStringLiteral("visible"); } static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); } static inline QString noAttributeValue() { return QStringLiteral("no"); } @@ -147,7 +149,7 @@ static QString extractSnippet(const QString &code, const QString &snippetLabel) } else if (useLine) result += line.toString() + QLatin1Char('\n'); } - return result; + return CodeSnipAbstract::fixSpaces(result); } template <class EnumType, Qt::CaseSensitivity cs = Qt::CaseInsensitive> @@ -295,7 +297,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive, }; ENUM_LOOKUP_LINEAR_SEARCH() -ENUM_LOOKUP_BEGIN(ContainerTypeEntry::Type, Qt::CaseSensitive, +ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive, containerTypeFromAttribute, ContainerTypeEntry::NoContainer) { {u"list", ContainerTypeEntry::ListContainer}, @@ -382,6 +384,7 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, {u"replace-type", StackElement::ReplaceType}, {u"smart-pointer-type", StackElement::SmartPointerTypeEntry}, {u"suppress-warning", StackElement::SuppressedWarning}, + {u"system-include", StackElement::SystemInclude}, {u"target-to-native", StackElement::TargetToNative}, {u"template", StackElement::Template}, {u"typedef-type", StackElement::TypedefTypeEntry}, @@ -390,6 +393,17 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, }; ENUM_LOOKUP_BINARY_SEARCH() +ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive, + visibilityFromAttribute, TypeSystem::Visibility::Unspecified) +{ + {u"no", TypeSystem::Visibility::Invisible}, + {u"false", TypeSystem::Visibility::Invisible}, + {u"auto", TypeSystem::Visibility::Auto}, + {u"yes", TypeSystem::Visibility::Visible}, + {u"true", TypeSystem::Visibility::Visible}, +}; +ENUM_LOOKUP_LINEAR_SEARCH() + static int indexOfAttribute(const QXmlStreamAttributes &atts, QStringView name) { @@ -625,6 +639,14 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) { m_error.clear(); m_currentPath.clear(); + m_smartPointerInstantiations.clear(); + const bool result = parseXml(reader) && setupSmartPointerInstantiations(); + m_smartPointerInstantiations.clear(); + return result; +} + +bool TypeSystemParser::parseXml(QXmlStreamReader &reader) +{ const QString fileName = readerFileName(reader); if (!fileName.isEmpty()) m_currentPath = QFileInfo(fileName).absolutePath(); @@ -668,6 +690,62 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) return true; } +// Split a type list potentially with template types +// "A<B,C>,D" -> ("A<B,C>", "D") +static QStringList splitTypeList(const QString &s) +{ + QStringList result; + int templateDepth = 0; + int lastPos = 0; + const int size = s.size(); + for (int i = 0; i < size; ++i) { + switch (s.at(i).toLatin1()) { + case '<': + ++templateDepth; + break; + case '>': + --templateDepth; + break; + case ',': + if (templateDepth == 0) { + result.append(s.mid(lastPos, i - lastPos).trimmed()); + lastPos = i + 1; + } + break; + } + } + if (lastPos < size) + result.append(s.mid(lastPos, size - lastPos).trimmed()); + return result; +} + +bool TypeSystemParser::setupSmartPointerInstantiations() +{ + for (auto it = m_smartPointerInstantiations.cbegin(), + end = m_smartPointerInstantiations.cend(); it != end; ++it) { + auto smartPointerEntry = it.key(); + const auto instantiationNames = splitTypeList(it.value()); + SmartPointerTypeEntry::Instantiations instantiations; + instantiations.reserve(instantiationNames.size()); + for (const auto &instantiationName : instantiationNames) { + const auto types = m_database->findCppTypes(instantiationName); + if (types.isEmpty()) { + m_error = + msgCannotFindTypeEntryForSmartPointer(instantiationName, + smartPointerEntry->name()); + return false; + } + if (types.size() > 1) { + m_error = msgAmbiguousTypesFound(instantiationName, types); + return false; + } + instantiations.append(types.constFirst()); + } + smartPointerEntry->setInstantiations(instantiations); + } + return true; +} + bool TypeSystemParser::endElement(const QStringRef &localName) { if (m_ignoreDepth) { @@ -715,11 +793,6 @@ bool TypeSystemParser::endElement(const QStringRef &localName) centry->setFieldModifications(m_contextStack.top()->fieldMods); centry->setCodeSnips(m_contextStack.top()->codeSnips); centry->setDocModification(m_contextStack.top()->docModifications); - - if (centry->designatedInterface()) { - centry->designatedInterface()->setCodeSnips(m_contextStack.top()->codeSnips); - centry->designatedInterface()->setFunctionModifications(m_contextStack.top()->functionMods); - } } break; case StackElement::AddFunction: { @@ -802,7 +875,7 @@ bool TypeSystemParser::endElement(const QStringRef &localName) break; default: break; // nada - }; + } break; default: break; @@ -878,7 +951,7 @@ bool TypeSystemParser::characters(const String &ch) break; default: Q_ASSERT(false); - }; + } return true; } } @@ -1110,6 +1183,7 @@ SmartPointerTypeEntry * QString smartPointerType; QString getter; QString refCountMethodName; + QString instantiations; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); if (name == QLatin1String("type")) { @@ -1118,6 +1192,8 @@ SmartPointerTypeEntry * getter = attributes->takeAt(i).value().toString(); } else if (name == QLatin1String("ref-count-method")) { refCountMethodName = attributes->takeAt(i).value().toString(); + } else if (name == QLatin1String("instantiations")) { + instantiations = attributes->takeAt(i).value().toString(); } } @@ -1152,6 +1228,7 @@ SmartPointerTypeEntry * auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); + m_smartPointerInstantiations.insert(type, instantiations); return type; } @@ -1201,7 +1278,7 @@ ContainerTypeEntry * return nullptr; } const QStringRef typeName = attributes->takeAt(typeIndex).value(); - ContainerTypeEntry::Type containerType = containerTypeFromAttribute(typeName); + ContainerTypeEntry::ContainerKind containerType = containerTypeFromAttribute(typeName); if (containerType == ContainerTypeEntry::NoContainer) { m_error = QLatin1String("there is no container of type ") + typeName.toString(); return nullptr; @@ -1251,40 +1328,6 @@ EnumTypeEntry * return entry; } -ObjectTypeEntry * - TypeSystemParser::parseInterfaceTypeEntry(const QXmlStreamReader &, - const QString &name, const QVersionNumber &since, - QXmlStreamAttributes *attributes) -{ - if (!checkRootElement()) - return nullptr; - auto *otype = new ObjectTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(otype, attributes); - QString targetLangName = name; - bool generate = true; - for (int i = attributes->size() - 1; i >= 0; --i) { - const QStringRef name = attributes->at(i).qualifiedName(); - if (name == targetLangNameAttribute()) { - targetLangName = attributes->takeAt(i).value().toString(); - } else if (name == generateAttribute()) { - generate = convertBoolean(attributes->takeAt(i).value(), - generateAttribute(), true); - } - } - - auto itype = new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), - since, currentParentTypeEntry()); - itype->setTargetLangName(targetLangName); - - if (generate) - itype->setCodeGeneration(m_generate); - else - itype->setCodeGeneration(TypeEntry::GenerateForSubclass); - - otype->setDesignatedInterface(itype); - itype->setOrigin(otype); - return otype; -} NamespaceTypeEntry * TypeSystemParser::parseNamespaceTypeEntry(const QXmlStreamReader &reader, @@ -1294,8 +1337,8 @@ NamespaceTypeEntry * if (!checkRootElement()) return nullptr; QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); + auto visibility = TypeSystem::Visibility::Unspecified; applyCommonAttributes(result.data(), attributes); - applyComplexTypeAttributes(reader, result.data(), attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef attributeName = attributes->at(i).qualifiedName(); if (attributeName == QLatin1String("files")) { @@ -1318,9 +1361,24 @@ NamespaceTypeEntry * return nullptr; } result->setExtends(*extendsIt); + } else if (attributeName == visibleAttribute()) { + const auto attribute = attributes->takeAt(i); + visibility = visibilityFromAttribute(attribute.value()); + if (visibility == TypeSystem::Visibility::Unspecified) { + qCWarning(lcShiboken, "%s", + qPrintable(msgInvalidAttributeValue(attribute))); + } + } else if (attributeName == generateAttribute()) { + if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true)) + visibility = TypeSystem::Visibility::Invisible; } } + if (visibility != TypeSystem::Visibility::Unspecified) + result->setVisibility(visibility); + // Handle legacy "generate" before the common handling + applyComplexTypeAttributes(reader, result.data(), attributes); + if (result->extends() && !result->hasPattern()) { m_error = msgExtendingNamespaceRequiresPattern(name); return nullptr; @@ -1482,9 +1540,6 @@ void TypeSystemParser::applyComplexTypeAttributes(const QXmlStreamReader &reader if (ctype->type() != TypeEntry::ContainerType) ctype->setTargetLangPackage(package); - if (InterfaceTypeEntry *di = ctype->designatedInterface()) - di->setTargetLangPackage(package); - if (generate) ctype->setCodeGeneration(m_generate); else @@ -2420,7 +2475,7 @@ bool TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes, CodeSni "// START of custom code block [file: " << source << "]\n" << extractSnippet(QString::fromUtf8(codeFile.readAll()), snippetLabel) - << "\n// END of custom code block [file: " << source + << "// END of custom code block [file: " << source << "]\n// ========================================================================\n"; snip->addCode(content); return true; @@ -2499,7 +2554,7 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, QString location; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); - if (name == QLatin1String("file-name")) + if (name == fileNameAttribute()) fileName = attributes->takeAt(i).value().toString(); else if (name == locationAttribute()) location = attributes->takeAt(i).value().toString(); @@ -2520,10 +2575,18 @@ bool TypeSystemParser::parseInclude(const QXmlStreamReader &, m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); return false; } - if (InterfaceTypeEntry *di = entry->designatedInterface()) { - di->setInclude(entry->include()); - di->setExtraIncludes(entry->extraIncludes()); + return true; +} + +bool TypeSystemParser::parseSystemInclude(const QXmlStreamReader &, + QXmlStreamAttributes *attributes) +{ + const int index = indexOfAttribute(*attributes, fileNameAttribute()); + if (index == -1) { + m_error = msgMissingAttribute(fileNameAttribute()); + return false; } + TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString()); return true; } @@ -2684,8 +2747,8 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) m_currentDroppedEntry = element; m_currentDroppedEntryDepth = 1; if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("Type system entry '%1' was intentionally dropped from generation.").arg(identifier); + qCInfo(lcShiboken, "Type system entry '%s' was intentionally dropped from generation.", + qPrintable(identifier)); } return true; } @@ -2761,14 +2824,6 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) element->entry = m_currentEnum; break; - case StackElement::InterfaceTypeEntry: - if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, versionRange.since, &attributes)) { - applyComplexTypeAttributes(reader, oe, &attributes); - element->entry = oe; - } else { - return false; - } - break; case StackElement::ValueTypeEntry: if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, ve, &attributes); @@ -2784,6 +2839,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) return false; break; case StackElement::ObjectTypeEntry: + case StackElement::InterfaceTypeEntry: if (!checkRootElement()) return false; element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); @@ -2805,7 +2861,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) break; default: Q_ASSERT(false); - }; + } if (element->entry) { if (!m_database->addType(element->entry, &m_error)) @@ -2828,6 +2884,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) || element->type == StackElement::LoadTypesystem || element->type == StackElement::InjectCode || element->type == StackElement::ExtraIncludes + || element->type == StackElement::SystemInclude || element->type == StackElement::ConversionRule || element->type == StackElement::AddFunction || element->type == StackElement::Template; @@ -2980,6 +3037,10 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) if (!addRejection(m_database, &attributes, &m_error)) return false; break; + case StackElement::SystemInclude: + if (!parseSystemInclude(reader, &attributes)) + return false; + break; case StackElement::Template: { const int nameIndex = indexOfAttribute(attributes, nameAttribute()); if (nameIndex == -1) { diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index d3ea54fc6..b4be2765c 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -31,6 +31,7 @@ #include "typesystem.h" #include <QtCore/QStack> +#include <QtCore/QHash> #include <QtCore/QScopedPointer> QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) @@ -86,6 +87,7 @@ class StackElement NativeToTarget = 0x1100, TargetToNative = 0x1200, AddConversion = 0x1300, + SystemInclude = 0x1400, SimpleMask = 0x3f00, // Code snip tags (0x1000, 0x2000, ... , 0xf000) @@ -151,6 +153,8 @@ public: QString errorString() const { return m_error; } private: + bool parseXml(QXmlStreamReader &reader); + bool setupSmartPointerInstantiations(); bool startElement(const QXmlStreamReader &reader); SmartPointerTypeEntry *parseSmartPointerEntry(const QXmlStreamReader &, const QString &name, @@ -184,9 +188,6 @@ private: const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); - ObjectTypeEntry * - parseInterfaceTypeEntry(const QXmlStreamReader &, const QString &name, - const QVersionNumber &since, QXmlStreamAttributes *); ValueTypeEntry * parseValueTypeEntry(const QXmlStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); @@ -247,6 +248,7 @@ private: StackElement* element, QXmlStreamAttributes *); bool parseInclude(const QXmlStreamReader &, const StackElement &topElement, TypeEntry *entry, QXmlStreamAttributes *); + bool parseSystemInclude(const QXmlStreamReader &, QXmlStreamAttributes *); TemplateInstance *parseTemplateInstanceEnum(const QXmlStreamReader &, const StackElement &topElement, QXmlStreamAttributes *); @@ -271,6 +273,7 @@ private: QString m_currentSignature; QString m_currentPath; QScopedPointer<TypeSystemEntityResolver> m_entityResolver; + QHash<SmartPointerTypeEntry *, QString> m_smartPointerInstantiations; }; #endif // TYPESYSTEMPARSER_H diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt index c1349cae6..3de5d3223 100644 --- a/sources/shiboken2/CMakeLists.txt +++ b/sources/shiboken2/CMakeLists.txt @@ -18,7 +18,9 @@ option(BUILD_TESTS "Build tests." TRUE) option(USE_PYTHON_VERSION "Use specific python version to build shiboken2." "") option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE) -find_package(Qt5 5.12 REQUIRED COMPONENTS Core) +set (QT_MAJOR_VERSION 5) +message(STATUS "Using Qt ${QT_MAJOR_VERSION}") +find_package(Qt${QT_MAJOR_VERSION} 5.12 REQUIRED COMPONENTS Core) if (QUIET_BUILD) set_quiet_build() @@ -64,13 +66,13 @@ set(shiboken2_library_so_version "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VER compute_config_py_values(shiboken2_VERSION) ## For debugging the PYTHON* variables -message("PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) -message("PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) -message("PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) -message("PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) -message("PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) -message("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) -message("PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}) +message(STATUS "PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) +message(STATUS "PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) +message(STATUS "PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) +message(STATUS "PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) +message(STATUS "PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) +message(STATUS "PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) +message(STATUS "PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}) if (NOT PYTHON_EXTENSION_SUFFIX) get_python_extension_suffix() @@ -112,7 +114,11 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_T # Force usage of the C++11 standard, without a silent fallback # to C++98 if the compiler does not support C++11. -set(CMAKE_CXX_STANDARD 11) +if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) + set(CMAKE_CXX_STANDARD 17) +else() + set(CMAKE_CXX_STANDARD 11) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) @@ -208,7 +214,7 @@ add_subdirectory(libshiboken) add_subdirectory(doc) # deps found, compile the generator. -if (Qt5Core_FOUND AND PYTHONINTERP_FOUND) +if (Qt${QT_MAJOR_VERSION}Core_FOUND AND PYTHONINTERP_FOUND) add_subdirectory(generator) add_subdirectory(shibokenmodule) diff --git a/sources/shiboken2/data/shiboken_helpers.cmake b/sources/shiboken2/data/shiboken_helpers.cmake index 6bd75d0ea..5e0c6ea72 100644 --- a/sources/shiboken2/data/shiboken_helpers.cmake +++ b/sources/shiboken2/data/shiboken_helpers.cmake @@ -244,7 +244,7 @@ macro(get_python_extension_suffix) " OUTPUT_VARIABLE PYTHON_EXTENSION_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) - message("PYTHON_EXTENSION_SUFFIX: " ${PYTHON_EXTENSION_SUFFIX}) + message(STATUS "PYTHON_EXTENSION_SUFFIX: " ${PYTHON_EXTENSION_SUFFIX}) endmacro() macro(get_llvm_config) @@ -260,7 +260,7 @@ macro(get_llvm_config) " OUTPUT_VARIABLE LLVM_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE) - message("LLVM_CONFIG: " ${LLVM_CONFIG}) + message(STATUS "LLVM_CONFIG: " ${LLVM_CONFIG}) endmacro() macro(get_python_arch) @@ -271,7 +271,7 @@ macro(get_python_arch) " OUTPUT_VARIABLE PYTHON_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) - message("PYTHON_ARCH: " ${PYTHON_ARCH}) + message(STATUS "PYTHON_ARCH: " ${PYTHON_ARCH}) endmacro() macro(shiboken_parse_all_arguments prefix type flags options multiopts) diff --git a/sources/shiboken2/doc/CMakeLists.txt b/sources/shiboken2/doc/CMakeLists.txt index 5903e9dfc..9fee96298 100644 --- a/sources/shiboken2/doc/CMakeLists.txt +++ b/sources/shiboken2/doc/CMakeLists.txt @@ -1,11 +1,47 @@ +cmake_minimum_required(VERSION 3.1) + find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") if (SPHINX) - message("-- sphinx-build - found") + message(STATUS "sphinx-build - found") configure_file(conf.py.in conf.py @ONLY) - add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) + # conditional tag for sphinx build + #string(JOIN "_" SPHINX_TAG ${DOC_OUTPUT_FORMAT} "format") + add_custom_target(doc + COMMAND ${SPHINX} -b ${DOC_OUTPUT_FORMAT} -c . ${CMAKE_CURRENT_SOURCE_DIR} html + COMMENT "Generating HTMLs..." + VERBATIM) + # Python script that will be called to update the QHP + set(py_cmd "from __future__ import print_function +import fileinput +import re +try: +\tfor line in fileinput.input('html/Shiboken.qhp',inplace=True,backup='.bak'): +\t\tline_copy=line.strip() +\t\tif not line_copy: # check for empty line +\t\t\tcontinue +\t\tmatch=re.match('(^.*virtualFolder.)doc(.*$)',line) +\t\tif match: +\t\t\trepl=''.join([match.group(1),'shiboken2',match.group(2)]) +\t\t\tprint(line.replace(match.group(0),repl),end=' ') +\t\telse: +\t\t\tprint(line) +except: +\tpass\n") + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/py_script.py + CONTENT ${py_cmd}) + + # create a custom command to generate QCH + if(DOC_OUTPUT_FORMAT STREQUAL "qthelp") + file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/html/Shiboken.qhp QHP_FILE) + add_custom_command(TARGET doc POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} py_script.py # ${CMAKE_CURRENT_BINARY_DIR}/html/Shiboken.qhp + COMMAND qhelpgenerator ${QHP_FILE} + COMMENT "Genereting QCH based on the QHP..." + VERBATIM) + endif() else() - message("-- sphinx-build - not found! doc target disabled") + message(WARNING "sphinx-build - not found! doc target disabled") if (WIN32) # if jom is used and we have no sphinx, then jom will crash. # so for windows, we always create a doc target (until jom gets fixed...) diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/domainindex.html b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/domainindex.html new file mode 100644 index 000000000..c136cdd1c --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/domainindex.html @@ -0,0 +1,57 @@ +{# + basic/domainindex.html + ~~~~~~~~~~~~~~~~~~~~~~ + + Template for domain indices (module index, ...). + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{% extends "layout.html" %} +{% set title = indextitle %} +{% block extrahead %} +{{ super() }} +{% if not embedded and collapse_index %} + <script type="text/javascript"> + DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true; + </script> +{% endif %} +{% endblock %} +{% block body %} +<div class="section"> + {%- set curr_group = 0 %} + + <h1>{{ indextitle }}</h1> + + <div class="modindex-jumpbox"> + {%- for (letter, entries) in content %} + <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> + {%- if not loop.last %} | {% endif %} + {%- endfor %} + </div> + + <table class="indextable modindextable" cellspacing="0" cellpadding="2"> + {%- for letter, entries in content %} + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap"><td></td><td><a name="cap-{{ letter }}"> + <strong>{{ letter }}</strong></a></td><td></td></tr> + {%- for (name, grouptype, page, anchor, extra, qualifier, description) + in entries %} + {%- if grouptype == 1 %}{% set curr_group = curr_group + 1 %}{% endif %} + <tr{% if grouptype == 2 %} class="cg-{{ curr_group }}"{% endif %}> + <td>{% if grouptype == 1 -%} + <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ curr_group }}" + class="toggler" style="display: none" alt="-" /> + {%- endif %}</td> + <td>{% if grouptype == 2 %} {% endif %} + {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%} + <tt class="xref">{{ name|e }}</tt> + {%- if page %}</a>{% endif %} + {%- if extra %} <em>({{ extra|e }})</em>{% endif -%} + </td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %} + <em>{{ description|e }}</em></td></tr> + {%- endfor %} + {%- endfor %} + </table> +</div> +{% endblock %} diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/fakebar.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/fakebar.png Binary files differnew file mode 100644 index 000000000..b45830e00 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/fakebar.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg Binary files differnew file mode 100644 index 000000000..cd474efba --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_python.jpg diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png Binary files differnew file mode 100644 index 000000000..3bc03b7c7 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/logo_qt.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/minus.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/minus.png Binary files differnew file mode 100644 index 000000000..da1c5620d --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/minus.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/plus.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/plus.png Binary files differnew file mode 100644 index 000000000..b3cb37425 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/plus.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pyside.css b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pyside.css new file mode 100644 index 000000000..aee5e4420 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pyside.css @@ -0,0 +1,1943 @@ +@import url('cookie-confirm.css') screen; + +/* -- admonitions -- */ + +div.admonition { + margin: 1.5em 0 1.5em; + padding: 0; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.admonition code { + font-family: inherit; +} + +p.admonition-title + p { + padding-left: 1em; +} + +div.admonition a:after { + content: ', '; +} + +div.admonition a:last-child:after { + content: ''; +} + +.body { + width: 100% +} +.bodywrapper .admonition p.admonition-title { + margin-bottom:5px +} + +.bodywrapper .admonition p { + margin:0 +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +div.warning, div.seealso, div.note { + padding: 6px 0px 6px 10px; + border: none; +} + +div.warning { + background-color: #ffe4e4; +} + +div.seealso { + background-color: #fff2d6; +} + +div.note { + background-color: #f3f3f4; +} + +table.docutils { + margin-right: auto; + margin-bottom: 10px; + border: none; + width: initial; +} + +table.docutils.colwidths-given td { + float: none; +} + +table.docutils th, +table.docutils td { + padding-left:0; + border: none; +} + +table.docutils td ul { + margin:0 +} + +table.docutils td ul > li { + margin: 0 0 0.5em; +} +h2 em { + float: right; + font-size: 10px; + position: relative; + top: -20px; +} + +.document { + padding-bottom: 20px; +} + +.documentwrapper { + margin-left: 20px; +} + +.body blockquote { + border: none; + padding-left: 0; + margin-bottom: 1.5em; +} + +.sphinxsidebar { + float: left; + width: 186px; + padding: 25px; + text-align: left; + background-color: #fff; +} + +.sphinxsidebar ul { + padding: 0px; + margin: 0px; + list-style-position: inside; +} + +.sphinxsidebar > ul { + padding: 0px; + margin: 0px; +} + +.sphinxsidebar ul li li { + margin-left: 10px; + padding: 0px; + font-size: 0.95em; +} + +.sphinxsidebar ul a, +.sphinxsidebar p.topless a { + word-break: break-word; +} + +.sphinxsidebar h3, .sphinxsidebar h3 a { + color: #333; +} + +.sphinxsidebar p.topless { + margin: 1em 0 1em; +} + +.pysidetoc ul { + list-style: none; + padding: 0px; + margin: 0px; +} + +.pysidetoc em { + font-style: normal; +} + +.pysidetoc strong { + display: block; + padding: 5px; + margin: 0 10px 10px 0; + border: none; + background-color: #e2e2e2; +} + +.section .docutils.container td { + float:left; +} + +.hide { + display: none; +} + +/* copy-notice */ +.document + p { + margin-left: 255px; + width: 70%; + font-size: 0.75em; + margin: 0 35px 15px 280px; +} + +#searchbox { + border-top: 1px solid #989898; + padding-top: 10px; + margin-left: -10px; + margin-right: -10px; + padding-left: 10px; + padding-right: 10px; +} + +#search_button { + border: 1px solid #3A393A; + background-color: #3A393A; + color: white; + cursor: pointer; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + +} + +form { + margin: 0px; + padding: 0px; +} + +#searchbox h3 { + padding: 10px 0 0 0; + margin-bottom: 5px; +} + +/* search field */ +form #q { + width: 136px; + /* height: 22px; */ + /* border: none; */ + margin: 0px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + margin-top: 2px; + padding: 4px; + line-height: 22px; +} + +#search-results h2 { + display: none; +} + +#search-results h2 { + display: none; +} + +#search-results ul.search { + margin: 0px; + padding: 0px; +} + +ul.search div.context { + padding-left: 40px; +} + +#installation td { + text-align: center; + font-weight: bold; +} + +em { + color: inherit; + font-style:italic; +} + +/******** REL bar *********/ + +.related { + display: inline; +} + +.related h3 { + display: none; +} + +.align-center { + text-align: center; +} + +.contentstable { + width: 100%; +} + +.contentstable td { + padding-left: 30px; + vertical-align: top; +} + +p.biglink a { + font-size: 20px; +} + +dt:target, .highlight { + background-color: #fbe54e; +} + +p.highlight-link { + margin-top: 10px; + font-size: 0.8em; +} + +#synopsis table, table.field-list { + margin: 1em 0 1em 0; +} + +table.field-list tr { + text-align: left; +} + +tt.descname { + font-size: 120%; + font-weight: bold; +} + +#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul { + margin: 0; + padding: 6px; + border: 1px solid #ddd; + border-radius: 0; + background-color: #e2e2e2; +} + +#functions p, #virtual-functions p, #slots p, #signals p, #static-functions p { + margin: 0; + padding: 0; +} + +#functions li, #virtual-functions li, #slots li, #signals li, #static-functions li { + list-style: none; + margin: 5px; + padding: 0; + font-size: 90%; +} + +#synopsis span.pre { + color: #009491; + font-weight: bolder; +} + +#detailed-description .class dt, +#detailed-description .method dt, +#detailed-description .staticmethod dt, +#detailed-description .attribute dt { + margin: 0px; + margin-bottom: 10px; + padding: 10px; + font-weight: bold; + background-color: #e2e2e2; + border: none; + border-radius: 0; +} + +#detailed-description dd > blockquote, +#detailed-description dd > .field-list { + font-family: monospace; + font-size: small; + border-left: 10px solid #e2e2e2; + padding-left: 10px; + margin-bottom: 1.5em; +} + +#detailed-description dd > blockquote blockquote { + border: none; + padding: 0; +} + +#detailed-description .class .field-odd, +#detailed-description .method .field-odd, +#detailed-description .staticmethod .field-odd, +#detailed-description .attribute .field-odd { + margin: 0; + padding: 1px 0 0 0; + background-color: #ffffff; + +} + +#detailed-description .class .field-even, +#detailed-description .method .field-even, +#detailed-description .staticmethod .field-even, +#detailed-description .attribute .field-even { + margin: 0; + padding: 1px 0 0 0; + background-color: #ffffff; +} + +#detailed-description .class .field-odd li, +#detailed-description .method .field-odd li, +#detailed-description .staticmethod .field-odd li, +#detailed-description .attribute .field-odd li { + list-style: none; + margin: 0; + padding: 0; + +} + +#detailed-description .class .field-even li, +#detailed-description .method .field-even li, +#detailed-description .staticmethod .field-even li, +#detailed-description .attribute .field-even li { + list-style: none; + margin: 0; + padding: 0; +} + +#detailed-description .class .field-odd p, +#detailed-description .method .field-odd p, +#detailed-description .staticmethod .field-odd p, +#detailed-description .attribute .field-odd p{ + margin: 0; + margin-left: 20px; + +} + +#detailed-description .class .field-even p, +#detailed-description .method .field-even p, +#detailed-description .staticmethod .field-even p, +#detailed-description .attribute .field-even p{ + margin: 0; + margin-left: 20px; +} + +#detailed-description .class .field-odd p:last-child, +#detailed-description .method .field-odd p:last-child, +#detailed-description .staticmethod .field-odd p:last-child, +#detailed-description .attribute .field-odd p:last-child { + margin-bottom: 10px; + +} + +#detailed-description .class .field-even p:last-child, +#detailed-description .method .field-even p:last-child, +#detailed-description .staticmethod .field-even p:last-child, +#detailed-description .attribute .field-even p:last-child{ + margin-bottom: 10px; +} + +.document dl.attribute, +.document dl.class, +.document dl.method, +.document dl.staticmethod { + margin-top: 2em; +} + +.document dl.attribute dd, +.document dl.class dd, +.document dl.method dd, +.document dl.staticmethod dd { + padding-left: 1em; +} + +#detailed-description .attribute td:nth-child(1) { + font-family: monospace; +} + +/* Qt theme */ +#navbar { + position:fixed; + top:0; + left:0; + z-index:100; + background:#fff; + width:100% +} +#navbar .container, .fixed .container { + max-width:1280px; + margin:0 auto; + padding:0 3.9%; /* 0? */ + position:relative; + overflow:visible +} +#navbar .navbar-header { + position:relative +} +#menuextras li a:hover span { + color: #41cd52; +} +/* new header */ +#mm-wrap, #mm-wrap #mm-helper, +#mm-wrap #mm-helper li.mm-item, +#mm-wrap #mm-helper a.mm-link { + -moz-transition: none; + -o-transition: none; + -webkit-transition: none; + transition: none; + -webkit-border-radius: 0 0 0 0; + -moz-border-radius: 0 0 0 0; + -ms-border-radius: 0 0 0 0; + -o-border-radius: 0 0 0 0; + border-radius: 0 0 0 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + -ms-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; + background: none; + border: 0; + bottom: auto; + box-sizing: border-box; + clip: auto; + color: #090e21; + display: block; + float: none; + font-family: inherit; + font-size: 14px; + height: auto; + left: auto; + line-height: 1.7; + list-style-type: none; + margin: 0; + min-height: 0; + opacity: 1; + outline: none; + overflow: visible; + padding: 0; + position: relative; + right: auto; + text-align: left; + text-decoration: none; + text-transform: none; + top: auto; + vertical-align: baseline; + visibility: inherit; + width: auto; +} +#mm-wrap #mm-helper { + visibility:visible; + text-align:right; + padding:0 0px 0 0px +} +#navbar #mm-wrap #mm-helper li.mm-item { + border-right:solid #f3f3f4 1px; + padding-right:30px; + padding-left:30px +} +#navbar #mm-wrap #mm-helper li.mm-item > a:hover { + opacity: .5 +} +#mm-wrap #mm-helper > li.mm-item { + margin:0 0 0 0; + display:inline-block; + height:auto; + vertical-align:middle +} +#navbar #mm-wrap #mm-helper li.mm-item:nth-child(3) { + border-right:0 +} +#mm-wrap #mm-helper a.mm-link { + cursor: pointer +} +@media (max-width: 1279px) { + #navbar { + padding:0; + position:relative; + } + #navbar .container { + max-width:100% + } + .container { + padding:0 2% + } +} +#navbar .navbar-oneQt { + display:inline; + float:left; + width:31px; + color:#41cd52 +} +#navbar .navbar-oneQt:before { + content:attr(data-icon); + position:absolute; + top:14px; + left:0; + color:#41cd52; + font-family:'Qt Icons'; + line-height:1; + font-size:40px; + transition:all 0.3s ease-in-out; +} +#mm-wrap { + clear:both; + background:rgba(255, 255, 255, 0.1); + -webkit-border-radius:0px 0px 0px 0px; + -moz-border-radius:0px 0px 0px 0px; + -ms-border-radius:0px 0px 0px 0px; + -o-border-radius:0px 0px 0px 0px; + border-radius:0px 0px 0px 0px +} +#mm-wrap #mm-helper li.mm-item:last-child a { + background:transparent url("icon_avatar.png") 50% 50% no-repeat !important; + background-size:24px !important; + width:24px !important; + height:24px !important; +} +#navbar #mm-wrap #mm-helper li.mm-item > a { + opacity:1; + -webkit-transition:all 0.3s ease-in-out; + -moz-transition:all 0.3s ease-in-out; + -ms-transition:all 0.3s ease-in-out; + -o-transition:all 0.3s ease-in-out; + transition:all 0.3s ease-in-out; +} +#mm-wrap #mm-helper > li.mm-item > a.mm-link { + border-top:0px solid #fff; + border-left:0px solid #fff; + border-right:0px solid #fff; + border-bottom:0px solid #fff; + outline:none; + text-decoration:none; + padding:0 0 0 0; + line-height:70px; + font-weight:normal; + height:70px; + vertical-align:baseline; + text-align:left; + width:auto; + display:block; + color:#090e21; + text-transform:none; + text-decoration:none; + background:rgba(0, 0, 0, 0); + -webkit-border-radius:0px 0px 0px 0px; + -moz-border-radius:0px 0px 0px 0px; + -ms-border-radius:0px 0px 0px 0px; + -o-border-radius:0px 0px 0px 0px; + border-radius:0px 0px 0px 0px; + font-family:inherit; + font-size:14px; +} +/* end new header */ +@media (min-width: 1320px) { + .body .flowListDiv dl.flowList { + -webkit-column-count:3; + -moz-column-count:3; + column-count:3 + } +} +@media (min-width: 1120px) { + #navbar.fixed { + -moz-box-shadow:0px 0px 8px rgba(0,0,0,0.23); + -webkit-box-shadow:0px 0px 8px rgba(0,0,0,0.23); + box-shadow:0px 0px 8px rgba(0,0,0,0.23) + } + #navbar.fixed #mm-wrap #mm-helper > li.mm-item > a.mm-link { + height:50px; + line-height:50px + } + #navbar.fixed .navbar-oneQt:before { + font-size:35px; + top:7px + } + + .flowListDiv dl.flowList { + -webkit-column-count:2; + -moz-column-count:2; + column-count:2 + } +} +@media (max-width: 1120px) { + #navbar { + padding:0; + position:relative + } + #navbar .navbar-oneQt:before { + left:10px + } + #navbar .container { + max-width:100%; + padding:0 + } + #footerbar .container { + padding:0 + } + body .main { + margin-top:0px + } + #footerbar .footer-main .footer-nav { + padding:3.9% 0 3.9% 3%; + border-bottom:1px solid #413d3b; + float:none; + display:block; + width:auto + } + #footerbar .footer-main .theqtcompany { + clear:both; + float:left; + margin:30px 0 8px 3% + } + #footerbar .footer-main .footer-social { + float:left; + padding:50px 0px 0px 3% + } + #footerbar #menu-footer-submenu { + clear:both; + float:none; + display:block; + padding:0px 0px 3.9% 3% + } + ul#menu-footer-submenu { + margin-left: 0 + } +} +.cookies_yum { + background-color:#cecfd5; + display:none; + width:100% +} +.cookies_yum img { + width:25px; + top:6px; + display:inline-block; + position:absolute; + left:13px +} +.cookies_yum div { + margin:0 auto; + max-width:1280px; + min-height:30px; + padding:6px 0px 6px 0px; + position:relative +} +.cookies_yum p { + color:#09102b; + margin:0px; + font-size:0.79em; + display:inline-block; + line-height:1.2; + padding:0 30px 0 50px +} +.cookies_yum p a { + white-space:nowrap +} +.cookies_yum a:hover { + color:#46a2da +} +.cookies_yum .close { + width:15px; + height:15px; + background-image:url("cookiebar-x.png"); + background-size:15px 30px; + background-position:top left; + cursor:pointer; + top:13px; + right:13px; + position:absolute; + transition:none +} +.cookies_yum .close:hover { + background-position:bottom left +} +#sidebar-toggle,#toc-toggle { + width:24px; + height:14px; + background-size:24px 28px; + cursor:pointer; + background-image:url("list_expand.png"); + float:right +} +#sidebar-toggle.collapsed, +#toc-toggle.collapsed { + background-position:bottom left +} +#sidebar-content > h2 { + display:none +} +#footerbar { + background:#222840; + color:#fff; + font-size: 0.9em; +} +#footerbar.fixed { + bottom:0; + left:0; + width:100% +} +#footerbar .footer-nav { + display:inline; + float:left +} +#footerbar .footer-main .footer-nav li { + float:left; + margin-right:1em +} +#footerbar .footer-main .footer-nav li a { + display:block; + padding:30px 0 10px 0; + line-height:20px; + height:20px; + color:#fff; + font-weight: 600; +} +#footerbar .footer-main .footer-nav li a:hover,#footerbar .footer-main .footer-nav li.current-menu-item a { + color:#eee +} +#footerbar .footer-main .footer-nav .sub-menu { + margin-left:0; + margin-bottom:0 +} +#footerbar .footer-main .footer-nav .sub-menu li { + float:none; + width: 100%; +} +#footerbar .footer-main .footer-nav .sub-menu ul { + padding:1px 1em; + font-size:0.786em; + line-height:8px; + float:none; + color:#5d5b59; + margin-bottom:0 +} +#footerbar .footer-main .footer-nav .sub-menu li a { + padding:2px 0; + font-size:1em; + float:none; + color:#cecfd5; + font-weight: 400; +} +#footerbar .footer-main .footer-nav .sub-menu li a:hover,#footerbar .footer-main .footer-nav .sub-menu li.current-menu-item a { + color:#eee +} +#footerbar .theqtcompany { + background:url("theqtcompany.png") no-repeat; + background-size:100%; + width:215px; + height:68px; + display:inline; + float:right; + margin:29px 0 28px 30px +} +#footerbar .footer-social { + display:inline; + float:right; + width:164px +} +#footerbar .footer-main .footer-social>div { + margin-left:0.1em; + margin-bottom:10px +} +#footerbar .disclaimer { + font-size:0.786em; + line-height:2.73; + color:#868584; + padding-top:20px; + padding-bottom:0.5% +} +#footerbar .disclaimer a { + color:#bdbebf +} +#footerbar .disclaimer a:hover { + color:#d6d6d6 +} +#footerbar .disclaimer ul li { + float:left; + vertical-align:middle; + margin-left:1.18em +} +#footerbar .disclaimer ul li:first-child { + margin-left:0 +} +#footerbar .disclaimer ul.lang-selector a { + color:#506a34; + color:rgba(128,195,66,0.3) +} +#footerbar .disclaimer ul.lang-selector a:hover { + color:#80c342; + color:rgba(128,195,66,0.7) +} +#menu-footer-menu, #menu-footer-menu ul { + margin-left:0; + margin-bottom:0 +} +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 400; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot"); + /* IE9 Compat Modes */ + src: local("Titillium Web"), local("TitilliumWeb-Regular"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +/* titillium-web-italic - latin_latin-ext */ +@font-face { + font-family: 'Titillium Web'; + font-style: italic; + font-weight: 400; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot"); + /* IE9 Compat Modes */ + src: local("Titillium WebItalic"), local("TitilliumWeb-Italic"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +/* titillium-web-600 - latin_latin-ext */ +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 600; + src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot"); + /* IE9 Compat Modes */ + src: local("Titillium WebSemiBold"), local("TitilliumWeb-SemiBold"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.svg#TitilliumWeb") format("svg"); + /* Legacy iOS */ +} +@font-face { + font-family:monospace; + font-style:normal; + font-weight:400; + src:local("Droid Sans Mono"),local("DroidSansMono"),url(//fonts.gstatic.com/s/droidsansmono/v7/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff) format("woff") +} +@font-face { + font-family:'Qt Icons'; + src:url("../style/icomoon.eot?-tgjuoj"); + src:url("../style/icomoon.eot?#iefix-tgjuoj") format("embedded-opentype"),url("../style/icomoon.woff?-tgjuoj") format("woff"),url("../style/icomoon.ttf?-tgjuoj") format("truetype"),url("../style/icomoon.svg?-tgjuoj#icomoon") format("svg"); + font-weight:normal; + font-style:normal +} +@font-face { + font-family:'social-icons'; + src:url("../style/social-icons.eot?54625607"); + src:url("../style/social-icons.eot?54625607#iefix") format("embedded-opentype"), + url("../style/social-icons.woff?54625607") format("woff"); + font-weight:normal; + font-style:normal +} +.clearfix:before,.clearfix:after { + content:" "; + display:table +} +.clearfix:after { + clear:both +} +.clearfix { + *zoom:1 +} +.clearfix .right { + float:right +} +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { + margin:0; + padding:0; + border:0; + font-size:100%; + line-height: 1.4; +} +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { + vertical-align:baseline +} +h1,h2,h3,h4,h5,h6 { + font-weight:300 +} +.body h2,.body h3,.body h4,.body h5,.body h6 { + margin:1.5em 0 0.75em +} +.body h1 { + margin-bottom:0.75em; + font-size:2.25em; +} +.body h3.fn,.body h3.flags { + color:#26282a; + font-size:1.46em; + padding:15px 0 15px 0; + border-bottom:2px #eee solid; + word-wrap:break-word +} +.body .fngroup { + border-bottom:2px #eee solid; + padding-bottom:15px; + margin-bottom:1.5em +} +.body .fngroup h3.fngroupitem { + margin:0; + padding-bottom:0; + border:none +} +.body h3.fn .name, +.body h3 span.type, +.qmlname span.name { + font-weight: 400 +} +.qmlname { + font-size:1.46em +} +.qmlproto table { + border:none; + border-bottom:2px #eee solid +} +.qmlproto table p { + max-width:100% +} +.qmlproto table tr { + background-color:#fff +} +.qmlname td, .qmlname th { + border:none; + text-align:left; + padding:5px 0 0 0 +} +.qmlreadonly,.qmldefault { + padding:0 5px 0 5px; + font-size:0.75em; + background-color:#eee; + float:right +} +.qmlreadonly { + color:#414141 +} +.qmldefault { + color:#D14141 +} +.rightAlign { + padding:3px 5px 3px 10px; + text-align:right +} +.centerAlign.functionIndex { + text-align:center; + font-size:150%; + margin-bottom: 1em +} +article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { + display:block +} +body { + line-height:1.25em; + font-family: Arial, Helvitica; + font-weight:400; + transition-duration:1s; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 16px; + background-color:#f3f3f4; + color:#404244; +} +ol,ul { + list-style-type: square; + #color: #17a81a; +} +.body ol,.body ul { + margin-top:0.75em; + margin-left:20px +} +.bodywrapper ol>li { + list-style-type:decimal; + margin-left:15px +} +.bodywrapper ol.a >li { + list-style-type:lower-alpha; +} +.bodywrapper ol.A >li { + list-style-type:upper-alpha; +} +.bodywrapper ol.i >li { + list-style-type:lower-roman; +} +.bodywrapper ol.I >li { + list-style-type:upper-roman; +} +.body li p { + margin-top:1em +} +blockquote,q { + quotes:none; + border-left:10px solid #ddd; + padding-left:10px +} +blockquote:before,blockquote:after,q:before,q:after { + content:''; + content:none; + width:100% +} +table { + border-collapse:collapse; + border-spacing:0; + margin-bottom:5px; + width:100% +} +a { + color:#17a81a; + text-decoration:none; + transition-duration:0.3s +} +a:hover { + color:#17a81a +} +.main,#footerbar>div { + max-width:1280px; + width:95%; + margin:0 auto +} +.main { + margin-top:80px +} +@media (max-width: 1120px) { + .main,.navbar-header,#footerbar>div { + width: 100%; + margin: 0; + } + .main .main-rounded { + padding: 0 15px; + } +} +.main_index { + background-color:#fff +} +.sectionlist { + margin-bottom:2em +} +[class*="col-"] { + letter-spacing:normal +} +.landing,.main_index .row { + letter-spacing:-0.31em +} +.main_index .row>div { + letter-spacing:normal +} +.col-1,.body { + display:inline-block; + background-color:#fff; + padding: 25px 35px 20px 30px; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; +} +.col-1 h2 { + font-size:1.8em; + font-weight:300; + line-height:1.1; + margin-bottom:0.83em; + margin-top:1em +} +.icons1of3 img { + display:inline-block; + float:left; + margin-right:0.75em; + margin-top:-5px; + width:2.75em +} +div.multi-column { + position:relative +} +div.multi-column div { + display:-moz-inline-box; + display:inline-block; + vertical-align:top; + margin-top:1em; + margin-right:2em; + width:16em +} +.sidebar { + display:block; + position:relative; + position:sticky; + float:left; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + width:20%; + padding-right:20px +} +.sidebar li { + text-overflow:ellipsis; + overflow:hidden +} +.toc,.sectionlist { + padding:25px; + background-color:#fff; + margin-bottom:1.25em +} +.sidebar .sectionlist p { + margin-bottom:0 +} +.sectionlist.promo { + padding:0; + background-color:#f3f3f4 +} +.sidebar-content:empty { + display:none; + visibility:hidden +} +.col-2 h2,.toc h3,.sidebar-content h2, +.sidebar-content h3,.sectionlist h2, +.sphinxsidebar { + position: fixed; + overflow: scroll; + overflow-x: hidden; + overflow-y: hidden; +} +.sphinxsidebar h3 { + font-weight: bold; + margin-bottom:1em; +} +.toc h3 a { + color:#404244 +} +.title { + font-size:2.25em; + font-weight:300; + letter-spacing:-1px; + line-height:1.15em; + margin-bottom:0.5em; + word-wrap:break-word +} +.navigationbar,col-1 h2 { + font-size:0.85em +} +.navigationbar h1 { + font-size:2.5em; + margin-bottom:0.85em; + margin-top:0.85em +} +.navigationbar li { + display:inline-block; + margin-right:5px; + position:relative; + padding-right:10px; + color:#585a5c +} +.navigationbar ul:last-of-type li a { + color:#404244 +} +.sectionlist li, .sphinxsidebar li { + padding-bottom: 10px; + line-height: 1.75em; +} +.col-1 ul { + margin-bottom:1.56em +} +.bodywrapper li { + margin-top:0.5em; + line-height:1.25em +} +.bodywrapper li.level2 { + margin-left:10px; + margin-top:0.4em; + font-size:0.9375em; +} +.bodywrapper p, +.bodywrapper dd { + line-height:1.25em; + margin:1em 0 1em; + color:#404244 +} +.bodywrapper b { + font-weight:600 +} +.body ul,.body ol { + /* margin-bottom:1.5em */ +} +.bodywrapper ul ul { + margin-top:0.5em +} +.bodywrapper .naviNextPrevious { + margin-top:25px; + max-width:100% +} +.naviNextPrevious.headerNavi, +p.naviNextPrevious + p { + display:none +} +.nextPage { + float:right +} +.prevPage:before { + content:"< " +} +.nextPage:after { + content:" >" +} +.navigationbar li a { + color:#404244 +} +.navigationbar li:after { + color:#404244; + content:"›"; + display:inline-block; + font-size:1.5em; + line-height:1; + position:absolute; + right:-2px; + top:-4px +} +.sub-navigation { + margin-top:10px +} +.navigationbar li:last-child:after,.sub-navigation li:after { + content:none +} +.navigationbar { + margin-bottom:10px; + line-height:1em +} +#buildversion { + margin-bottom:10px; + font-style:italic; + font-size:small; + float:right +} +.copy-notice { + width:75%; + font-size:0.75em; + margin:20px 35px 0 10px; + line-height:1.75em; + float:right; + color:#585a5c +} +.copy-notice.index { + margin-top:10px; + float:none +} +li a.active { + color:#585a5c +} +.flowList { + padding:25px +} +.flowListDiv dl { + -webkit-column-count:1; + -moz-column-count:1; + column-count:1 +} +.flowList dd { + display:inline-block; + margin-left:10px; + width:90%; + line-height:1.15em; + overflow-x:hidden; + text-overflow:ellipsis +} +.alphaChar { + font-size:2em; + position:absolute +} +.flowList.odd { + background-color:#f9f9f9 +} +.body ul>li,.doc-column ul>li { + list-style-image:url("list_arrow.png"); + margin-left:15px; + color:#404244; + margin-top:0.65em; + line-height:1em +} +.bodywrapper table p { + margin:0px; + padding:0px +} +.bodywrapper table p { + margin:0px; + padding:0px; + min-height:1.25em +} +.bodywrapper .qmldoc { + margin-top:0.75em +} +.body h2 { + margin-top: 1.5em; + font-size:1.75em +} +.body h3 { + font-size:1.35em +} +.body h4 { + font-size:1.15em +} +.body p img { + margin-top:0.75em; + max-width:100% +} +.body .border img { + box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5) +} +.body .border .player { + box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5) +} +.body p.figCaption { + transform:translateY(-30px); + color:#606366; + font-size:95%; + margin-left:3px; + font-style:italic +} +.body table { + width:initial; + vertical-align:initial +} +table .odd { + background-color:#f9f9f9 +} +table thead { + text-align:left; + padding-left:20px +} +table,table td,table th { + border:1px solid #eee +} +table td,table th { + padding:5px 20px; + line-height:1.3 +} +.body .fixed table td { + min-width:50%; + width:50% +} +table.alignedsummary,table.propsummary { + width:initial +} +table.valuelist td.tblval { + font-size:0.75em +} +div.main_index .row { + border-bottom:10px solid #f3f3f4 +} +div.main_index .row { + position:relative +} +div.main_index .row>div { + display:inline-block; + width:50%; + vertical-align:top; + padding:2em 3em; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box +} +div.main_index h2 { + font-size:2.1875em; + margin-bottom:1em +} +#search_bar { + width:40%; + float:right +} +div.main_index .row:after { + content:""; + position:absolute; + top:0; + right:50%; + height:100%; + width:10px; + background-color:#f3f3f4 +} +div.table { + overflow-x:auto +} +.body tr > td > pre { + font-size:0.75em +} +p.qt_commercial { + border:3px solid #5caa15; + margin:0 auto; + padding:15px; + width:28%; + text-align:center; + clear:both +} +h1.qt_commercial { + padding:20px; + background-color:#5caa15; + display:inline; + float:right; + font-size:1.25em; + line-height:1.25em; + height:1.25em; + color:#fff +} +div.qt_commercial { + border-top:5px solid #5caa15; + margin-bottom:50px +} +div.pre { + position:relative; + height:auto +} +pre, .LegaleseLeft { + background-color:#222840; + color:#fff; + display:block; + font-family:monospace; + line-height:1.5; + overflow-x:auto; + margin-bottom:25px; + padding:25px; + margin-top:0.75em; + font-size: .8em; +} +.bodywrapper .LegaleseLeft p { + color:#fff; + white-space: pre-wrap +} +pre .str,code .str { + color:#aaaaaa +} +pre .kwd,code .kwd { + color:#ffff55 +} +pre .com,code .com { + color:#55ffff +} +pre .typ,code .typ { + color:#4f9d08 +} +pre a .typ,code a .typ { + color:#21be2b +} +pre .lit,code .lit { + color:#ff55ff +} +pre .pun,code .pun { + color:#fff +} +pre .pln,code .pln { + color:#fff +} +@media print { + pre { + background-color:#eee !important + } + pre .str,code .str { + color:#060 + } + pre .kwd,code .kwd{ + color:#006; + font-weight:bold + } + pre .com,code .com { + color:#600 + } + pre .typ,code .typ { + color:#404; + font-weight:bold + } + pre .lit,code .lit { + color:#044 + } + pre .pun,code .pun { + color:#440 + } + pre .pln,code .pln { + color:#000 + } +} +pre.wrap { + white-space:pre-wrap +} +pre span.wrap { + display:none; + background:url("wrap.png") no-repeat; + right:0; + top:2px; + position:absolute; + width:20px; + height:14px; + margin:4px; + opacity:0.65 +} + +span.pre { + color: #09102d; +} + +span.wrap:hover { + opacity:1 +} +span.wrap:active { + opacity:0.75 +} +.copy_text { + background-color:#46a2da; + color:#fff; + border:2px solid #46a2da; + padding:10px 16px; + margin-left:-10px; + margin-top:-50px; + position:absolute; + opacity:0; + cursor:pointer; + float:right +} +.copy_text:hover { + background-color:#fff; + color:#46a2da +} +code,.codelike { + font-family:monospace; +} +#detailed-description .function dt > code, +#detailed-description .function dt > em { + font-weight:bold +} +h3.fn code { + font-size:0.75em; + float:right; + background-color:#eee; + padding:3px; + margin: 3px 0 0 20px +} +pre:hover>.copy_text { + display:inline-block; + opacity:1; + transition:0.5s ease +} +#main_title_bar { + background:url("pyside-logo.png") no-repeat; + background-size:100%; + width:366px; + height:86px; + margin:15px 0 15px 0 +} +#main_title_bar h1 { + visibility:hidden +} +#main_title_bar .search_bar { + letter-spacing:normal; + width:50%; + display:inline-block; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + vertical-align:middle +} +#main_title_bar h1 { + letter-spacing:normal; + display:inline-block; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + box-sizing:border-box; + vertical-align:middle +} +#main_title_bar .search_bar * { + letter-spacing:normal; + padding:0; + margin:0; + border:none +} +#sidebar-toggle,#toc-toggle { + display:none +} +@media (max-width: 980px) { + body { + font-size:calc-em(14px) + } + #main_title_bar>h1,#main_title_bar .search_bar { + width:100% + } + #main_title_bar .search_bar { + margin-bottom:15px + } + .main { + margin-top:0px + } + .main_index .row { + border:none !important + } + .title { + font-size:1.5em; + font-weight:400; + word-wrap:break-word + } + .col-1,.body,.naviNextPrevious,.sidebar { + padding:10px + } + .sidebar { + position:relative; + padding-top:0 + } + .search .sidebar { + display:none; + visibility:hidden + } + .col-2 h2,.toc h3,.sidebar-content h2,.sidebar-content h3,.sectionlist h2 { + text-align:center; + margin-bottom:5px + } + div.main_index .row:after { + content:none + } + div.main_index .row>div { + display:block !important; + width:100%; + padding:15px; + margin:0 + } + .body,.sidebar,.col-1 { + width:100% + } + .sidebar-content,.col-2,.toc { + background-color:#fff; + margin-bottom:1em; + padding:20px + } + #sidebar-toggle,#toc-toggle { + display:block + } + #sidebar-toggle.collapsed + h2 { + display:block + } + .bodywrapper p { + margin-bottom:1em; + max-width:100% + } + table td,table th { + padding:5px 5px + } + .sectionlist { + padding:0 + } + .sidebar > .sectionlist { + padding:20px + } + .sectionlist.promo { + max-width:46%; + margin:0 auto 1em auto; + float:left; + padding:0 2% + } + .sidebar .sidebar-content { + clear:both + } + .copy-notice { + float:none; + width:initial + } +} +[id]:target > *:first-child, +dt[id]:target { + -webkit-animation:highlighter 3s; + animation:highlighter 3s +} +@-webkit-keyframes highlighter { + 25% { + background-color:#d1e8f6; + color:#444 + } + 75% { + background-color:#d1e8f6; + color:#444 + } +} +@keyframes highlighter { + 25% { + background-color:#d1e8f6; + color:#444 + } + 75% { + background-color:#d1e8f6; + color:#444 + } +} +@-webkit-keyframes copypaste { + 25% { + opacity:1 + } + 100% { + border-radius:10px; + margin-top:-50px; + opacity:1 + } +} +@keyframes copypaste { + 25% { + opacity:1 + } + 100% { + border-radius:10px; + margin-top:-50px; + opacity:1 + } +} +#footer { + clear:both +} +.footer-social i { + font-family: "social-icons"; + font-style: normal; + font-size:150%; + margin: .55em; + color: #cecfd5 +} +.footer-social i:hover { + color: #eee +} +.footer-social .icon-twitter:before { + content: '\f099' +} +.footer-social .icon-facebook:before { + content: '\f09a' +} +.footer-social .icon-youtube:before { + content: '\f16a' +} +.menuextraslanguages { + display:none; + visibility:hidden +} + +input:focus { + border-color: #46a2da; + box-shadow: 0 0 5px #46a2da; + color: #000; +} + +.animation { + width: 100%; + border-style: none; + border-width: 0 +} + +.player { + width: auto; + position: relative; + display: table; + margin-bottom:1.5em; +} + +.playcontrol { + display: none; + background: url("play_icon.svg") no-repeat center, + linear-gradient( + rgba(0,0,0,0.15), rgba(0,0,0,0.15) + ); + background-size: 25%; + width: 100%; + height: 100%; + position: absolute; + left: 0%; + right: 0%; + top: 0%; + bottom: 0%; + margin: auto +} + +/* expand/collapse code sections */ +pre input { + display:none; + visibility:hidden +} +pre label { + display:block; + margin:-3px 3px 0 -16px; + text-align:center; + color:#21be2b; + float:left; +} +pre label:hover { + color:#fff +} +pre label::before { + font-weight:600; + font-size:16px; + content:"+"; + display:inline-block; + width:16px; + height:16px +} +#ec_expand { + height:16px; + overflow:hidden; + transition:height 0.35s; +} +#ec_expand::before { + content:"...*/"; + color:#aaa; + background-color:#3a4055; + z-index:99 !important; + right:25px; + position:absolute +} +#ec_toggle:checked ~ #ec_expand { + height:initial +} +#ec_toggle:checked ~ #ec_expand::before { + content:"" +} +#ec_toggle:checked ~ label::before { + content:"-" +} + +/* permalinks */ +h1:hover > .headerlink, +h2:hover > .plink, +h2:hover > .headerlink, +h3:hover > .plink, +h3:hover > .headerlink, +h4:hover > .plink, +h4:hover > .headerlink, +h5:hover > .plink, +h5:hover > .headerlink { + opacity:1 +} +a.plink, a.headerlink { + opacity: 0; + padding-left: 8px; + font-size: 0.8em; + font-weight: 600; + transition: opacity 180ms ease-in-out +} +a.plink::before { + content:'\00B6' +} + +table.special { + border: 3px; + padding: 0px; + border-collapse: separate; + border-spacing: 20px; + line-height: 1.5em; +} + +.special p { + text-align: center; + color: #3a4055; +} + +.special a { + display: block; + border-bottom: 0; + text-decoration: none; +} + +.special a:hover { + border-bottom: 0; + text-decoration: none; +} + +.special strong { + color: #17a81a; + font-size: 110%; + font-weight: normal; +} + +table.special th, +table.special td { + border: 1px solid #888; + padding-top: 14px; + padding-bottom: 14px; + padding-left: 6px; + padding-right: 5px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; +} + +.special td:hover { + padding-top: 2px; + padding-bottom: 2px; + border-bottom: 4px solid #41cd52; +} diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png Binary files differnew file mode 100644 index 000000000..3a2f2bd17 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/pysidelogo.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png Binary files differnew file mode 100644 index 000000000..4036733a7 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/static/relbar_bg.png diff --git a/sources/shiboken2/doc/_themes/pysidedocs_qthelp/theme.conf b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/theme.conf new file mode 100644 index 000000000..4384b459c --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs_qthelp/theme.conf @@ -0,0 +1,7 @@ +[theme] +inherit = default +stylesheet = pyside.css +pygments_style = none + +[options] +nosidebar = true diff --git a/sources/shiboken2/doc/conf.py.in b/sources/shiboken2/doc/conf.py.in index e158abbbe..f99af0fff 100644 --- a/sources/shiboken2/doc/conf.py.in +++ b/sources/shiboken2/doc/conf.py.in @@ -25,7 +25,12 @@ import sys, os extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.coverage'] +output_format='@DOC_OUTPUT_FORMAT@' + +def setup(app): + app.add_config_value('output_format','qthelp','env') rst_epilog = """ + .. |project| replace:: Shiboken """ @@ -158,3 +163,6 @@ html_show_sourcelink = False # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' + +# -- Options for qthelp output -------------------------------------------------- +qthelp_theme = 'pysidedocs_qthelp' diff --git a/sources/shiboken2/doc/index.rst b/sources/shiboken2/doc/index.rst index ca452b9ca..a6e1bccd4 100644 --- a/sources/shiboken2/doc/index.rst +++ b/sources/shiboken2/doc/index.rst @@ -1,7 +1,14 @@ Shiboken ******** -Shiboken is a fundamental piece on the `Qt for Python`_ project that serves two purposes: +.. ifconfig:: output_format == 'html' + + Shiboken is a fundamental piece on the `Qt for Python <../index.html>`_ project that serves two purposes: + +.. ifconfig:: output_format == 'qthelp' + + Shiboken is a fundamental piece on the `Qt for Python <../pyside2/index.html>`_ project that serves two purposes: + * Generator_: Extract information from C or C++ headers and generate CPython_ code that allow to bring C or C++ projects to Python. This process uses a library called ApiExtractor_ which @@ -9,7 +16,6 @@ Shiboken is a fundamental piece on the `Qt for Python`_ project that serves two * Module_: An utility Python module that exposed new Python types, functions to handle pointers, among other things, that is written in CPython_ and can use independently of the generator. -.. _`Qt for Python`: ../index.html .. _Generator: shibokengenerator.html .. _Module: shibokenmodule.html .. _CPython: https://github.com/python/cpython diff --git a/sources/shiboken2/doc/shibokengenerator.rst b/sources/shiboken2/doc/shibokengenerator.rst index 1a7152fbb..b15ad5ada 100644 --- a/sources/shiboken2/doc/shibokengenerator.rst +++ b/sources/shiboken2/doc/shibokengenerator.rst @@ -69,7 +69,7 @@ Usage :: - shiboken [options] header-file typesystem-file + shiboken [options] header-file(s) typesystem-file Options diff --git a/sources/shiboken2/doc/typesystem_specifying_types.rst b/sources/shiboken2/doc/typesystem_specifying_types.rst index bca1e0774..27267faab 100644 --- a/sources/shiboken2/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/doc/typesystem_specifying_types.rst @@ -153,6 +153,7 @@ namespace-type <typesystem> <namespace-type name="..." + visible="true | auto | false" generate="yes | no" package="..." since="..." @@ -161,8 +162,16 @@ namespace-type The **name** attribute is the name of the namespace, e.g., "Qt". - The *optional* **generate** attribute is used to inform if you need to prepend - the given namespace into each generated class. Its default value is **yes**. + The *optional* **visible** attribute is used specify whether the + namespace is visible in the target language name. Its default value is + **auto**. It means that normal namespaces are visible, but inline namespaces + (as introduced in C++ 11) will not be visible. + + The detection of inline namespaces requires shiboken to be built + using LLVM 9.0. + + The *optional* **generate** is a legacy attribute. Specifying + **no** is equivalent to **visible="false"**. The **package** attribute can be used to override the package of the type system. @@ -326,30 +335,7 @@ object-type interface-type ^^^^^^^^^^^^^^ - The interface-type node indicates that the given class is replaced by an - interface pattern when mapping from C++ to the target language. Using the - interface-type node implicitly makes the given type an :ref:`object-type`. - - .. code-block:: xml - - <typesystem> - <interface-type name="..." - since="..." - package ="..." - default-superclass ="..." - revision="..." /> - </typesystem> - - The **name** attribute is the fully qualified C++ class name. The *optional* - **package** attribute can be used to override the package of the type system. - If there is no C++ base class, the *optional* **default-superclass** attribute - can be used to specify a superclass in the generated target language API, for - the given class. - - The *optional* **since** value is used to specify the API version of this interface. - - The **revision** attribute can be used to specify a revision for each type, easing the - production of ABI compatible bindings. + This type is deprecated and no longer has any effect. Use object-type instead. .. _container-type: @@ -436,6 +422,14 @@ smart-pointer-type to function return values. **ref-count-method** specifies the name of the method used to do reference counting. + The *optional* attribute **instantiations** specifies for which instantiations + of the smart pointer wrappers will be generated (comma-separated list). + By default, this will happen for all instantiations found by code parsing. + This might be a problem when linking different modules, since wrappers for the + same instantiation might be generated into different modules, which then clash. + Providing an instantiations list makes it possible to specify which wrappers + will be generated into specific modules. + .. code-block:: xml <typesystem> @@ -443,7 +437,8 @@ smart-pointer-type since="..." type="..." getter="..." - ref-count-method="..."/> + ref-count-method="..." + instantiations="..."/> </typesystem> .. _function: @@ -467,3 +462,20 @@ function The function tag has two *optional* attributes: **since**, whose value is used to specify the API version of this function, and **rename**, to modify the function name. +.. _system_include: + +system-include +^^^^^^^^^^^^^^ + + The optional **system-include** specifies the name of a system include + file or a system include path (indicated by a trailing slash) to be + parsed. Normally, include files considered to be system include + files are skipped by the C++ code parser. Its primary use case + is exposing classes from the STL library. + + .. code-block:: xml + + <typesystem> + <system-include file-name="memory"/> + <system-include file-name="/usr/include/Qt/"/> + </typesystem> diff --git a/sources/shiboken2/generator/CMakeLists.txt b/sources/shiboken2/generator/CMakeLists.txt index 51623414b..1a3f4e5c4 100644 --- a/sources/shiboken2/generator/CMakeLists.txt +++ b/sources/shiboken2/generator/CMakeLists.txt @@ -20,7 +20,7 @@ target_include_directories(shiboken2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${apiextractor_SOURCE_DIR} ) -target_link_libraries(shiboken2 apiextractor Qt5::Core) +target_link_libraries(shiboken2 apiextractor Qt${QT_MAJOR_VERSION}::Core) if (NOT DISABLE_DOCSTRINGS) target_sources(shiboken2 PRIVATE qtdoc/qtdocgenerator.cpp) target_compile_definitions(shiboken2 PUBLIC DOCSTRINGS_ENABLED) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index 484b1f641..4eabb3d2c 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -151,6 +151,12 @@ QString DefaultValue::constructorParameter() const return m_value + QLatin1String("()"); } +QString GeneratorContext::smartPointerWrapperName() const +{ + Q_ASSERT(m_type == SmartPointer); + return m_preciseClassType->cppSignature(); +} + struct Generator::GeneratorPrivate { const ApiExtractor *apiextractor = nullptr; @@ -159,7 +165,6 @@ struct Generator::GeneratorPrivate QString licenseComment; QString moduleName; QStringList instantiatedContainersNames; - QStringList instantiatedSmartPointerNames; QVector<const AbstractMetaType *> instantiatedContainers; QVector<const AbstractMetaType *> instantiatedSmartPointers; @@ -211,6 +216,31 @@ QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType *type) return typeName; } +// Strip a "const QSharedPtr<const Foo> &" or similar to "QSharedPtr<Foo>" (PYSIDE-1016/454) +const AbstractMetaType *canonicalSmartPtrInstantiation(const AbstractMetaType *type) +{ + AbstractMetaTypeList instantiations = type->instantiations(); + Q_ASSERT(instantiations.size() == 1); + const bool needsFix = type->isConstant() || type->referenceType() != NoReference; + const bool pointeeNeedsFix = instantiations.constFirst()->isConstant(); + if (!needsFix && !pointeeNeedsFix) + return type; + auto fixedType = type->copy(); + fixedType->setReferenceType(NoReference); + fixedType->setConstant(false); + if (pointeeNeedsFix) { + auto fixedPointeeType = instantiations.constFirst()->copy(); + fixedPointeeType->setConstant(false); + fixedType->setInstantiations(AbstractMetaTypeList(1, fixedPointeeType)); + } + return fixedType; +} + +static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType *smartPtrType) +{ + return smartPtrType->instantiations().constFirst()->typeEntry(); +} + void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, const QString &context) { @@ -244,18 +274,15 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType m_d->instantiatedContainers.append(type); } } else { - // Is smart pointer. - if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { - m_d->instantiatedSmartPointerNames.append(typeName); - if (type->isConstant() || type->referenceType() != NoReference) { - // Strip a "const QSharedPtr<Foo> &" or similar to "QSharedPtr<Foo>" (PYSIDE-1016) - auto fixedType = type->copy(); - fixedType->setReferenceType(NoReference); - fixedType->setConstant(false); - type = fixedType; - } - m_d->instantiatedSmartPointers.append(type); - } + // Is smart pointer. Check if the (const?) pointee is already known + auto pt = pointeeTypeEntry(type); + const bool present = + std::any_of(m_d->instantiatedSmartPointers.cbegin(), m_d->instantiatedSmartPointers.cend(), + [pt] (const AbstractMetaType *t) { + return pointeeTypeEntry(t) == pt; + }); + if (!present) + m_d->instantiatedSmartPointers.append(canonicalSmartPtrInstantiation(type)); } } @@ -387,9 +414,9 @@ void Generator::setOutputDirectory(const QString &outDir) m_d->outDir = outDir; } -bool Generator::generateFileForContext(GeneratorContext &context) +bool Generator::generateFileForContext(const GeneratorContext &context) { - AbstractMetaClass *cls = context.metaClass(); + const AbstractMetaClass *cls = context.metaClass(); if (!shouldGenerate(cls)) return true; @@ -397,8 +424,6 @@ bool Generator::generateFileForContext(GeneratorContext &context) const QString fileName = fileNameForContext(context); if (fileName.isEmpty()) return true; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "generating: " << fileName; QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls) + QLatin1Char('/') + fileName; @@ -421,12 +446,28 @@ QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartP return fileName; } +GeneratorContext Generator::contextForClass(const AbstractMetaClass *c) const +{ + GeneratorContext result; + result.m_metaClass = c; + return result; +} + +GeneratorContext Generator::contextForSmartPointer(const AbstractMetaClass *c, + const AbstractMetaType *t) const +{ + GeneratorContext result; + result.m_metaClass = c; + result.m_preciseClassType = t; + result.m_type = GeneratorContext::SmartPointer; + return result; +} + bool Generator::generate() { const AbstractMetaClassList &classList = m_d->apiextractor->classes(); for (AbstractMetaClass *cls : classList) { - GeneratorContext context(cls); - if (!generateFileForContext(context)) + if (!generateFileForContext(contextForClass(cls))) return false; } @@ -440,8 +481,7 @@ bool Generator::generate() smartPointers))); return false; } - GeneratorContext context(smartPointerClass, type, true); - if (!generateFileForContext(context)) + if (!generateFileForContext(contextForSmartPointer(smartPointerClass, type))) return false; } return finishGeneration(); @@ -449,7 +489,8 @@ bool Generator::generate() bool Generator::shouldGenerateTypeEntry(const TypeEntry *type) const { - return type->codeGeneration() & TypeEntry::GenerateTargetLang; + return (type->codeGeneration() & TypeEntry::GenerateTargetLang) + && NamespaceTypeEntry::isVisibleScope(type); } bool Generator::shouldGenerate(const AbstractMetaClass *metaClass) const @@ -517,7 +558,9 @@ QTextStream &formatCode(QTextStream &s, const QString &code, Indentor &indentor) Q_ASSERT(emptyLine.isValid()); for (QString line : lst) { - if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) { + if (line.startsWith(QLatin1Char('#'))) { + s << line; // Do not indent preprocessor lines + } else if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) { while (line.constEnd()->isSpace()) line.chop(1); int limit = 0; @@ -529,7 +572,7 @@ QTextStream &formatCode(QTextStream &s, const QString &code, Indentor &indentor) s << indentor << line.remove(0, limit); } - s << endl; + s << Qt::endl; } return s; } @@ -670,6 +713,9 @@ DefaultValue Generator::minimalConstructor(const AbstractMetaType *type) const if (Generator::isPointer(type)) return DefaultValue(DefaultValue::Pointer, QLatin1String("::") + type->typeEntry()->qualifiedCppName()); + if (type->typeEntry()->isSmartPointer()) + return minimalConstructor(type->typeEntry()); + if (type->typeEntry()->isComplex()) { auto cType = static_cast<const ComplexTypeEntry *>(type->typeEntry()); if (cType->hasDefaultConstructor()) @@ -724,6 +770,9 @@ DefaultValue Generator::minimalConstructor(const TypeEntry *type) const : DefaultValue(DefaultValue::Custom, ctor); } + if (type->isSmartPointer()) + return DefaultValue(DefaultValue::DefaultConstructor, type->qualifiedCppName()); + if (type->isComplex()) return minimalConstructor(AbstractMetaClass::findClass(classes(), type)); @@ -893,8 +942,12 @@ static QString getClassTargetFullName_(const T *t, bool includePackageName) QString name = t->name(); const AbstractMetaClass *context = t->enclosingClass(); while (context) { - name.prepend(QLatin1Char('.')); - name.prepend(context->name()); + // If the type was marked as 'visible=false' we should not use it in + // the type name + if (NamespaceTypeEntry::isVisibleScope(context->typeEntry())) { + name.prepend(QLatin1Char('.')); + name.prepend(context->name()); + } context = context->enclosingClass(); } if (includePackageName) { diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h index dde281f0e..5a55422a1 100644 --- a/sources/shiboken2/generator/generator.h +++ b/sources/shiboken2/generator/generator.h @@ -146,24 +146,32 @@ private: * In the future the second case might be generalized for all template type instantiations. */ class GeneratorContext { + friend class ShibokenGenerator; + friend class Generator; public: - GeneratorContext() = default; - GeneratorContext(AbstractMetaClass *metaClass, - const AbstractMetaType *preciseType = nullptr, - bool forSmartPointer = false) - : m_metaClass(metaClass), - m_preciseClassType(preciseType), - m_forSmartPointer(forSmartPointer) {} + enum Type { Class, WrappedClass, SmartPointer }; + GeneratorContext() = default; - AbstractMetaClass *metaClass() const { return m_metaClass; } - bool forSmartPointer() const { return m_forSmartPointer; } + const AbstractMetaClass *metaClass() const { return m_metaClass; } const AbstractMetaType *preciseType() const { return m_preciseClassType; } + bool forSmartPointer() const { return m_type == SmartPointer; } + bool useWrapper() const { return m_type == WrappedClass; } + + QString wrapperName() const + { + Q_ASSERT(m_type == WrappedClass); + return m_wrappername; + } + + QString smartPointerWrapperName() const; + private: - AbstractMetaClass *m_metaClass = nullptr; + const AbstractMetaClass *m_metaClass = nullptr; const AbstractMetaType *m_preciseClassType = nullptr; - bool m_forSmartPointer = false; + QString m_wrappername; + Type m_type = Class; }; /** @@ -294,8 +302,12 @@ protected: /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or nullptr if not found. const AbstractMetaEnum *findAbstractMetaEnum(const AbstractMetaType *metaType) const; + virtual GeneratorContext contextForClass(const AbstractMetaClass *c) const; + GeneratorContext contextForSmartPointer(const AbstractMetaClass *c, + const AbstractMetaType *t) const; + /// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case). - bool generateFileForContext(GeneratorContext &context); + bool generateFileForContext(const GeneratorContext &context); /// Returns the file base name for a smart pointer. QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType, @@ -371,7 +383,7 @@ protected: * \return the file name used to write the binding code for the class */ virtual QString fileNameSuffix() const = 0; - virtual QString fileNameForContext(GeneratorContext &context) const = 0; + virtual QString fileNameForContext(const GeneratorContext &context) const = 0; virtual bool doSetup() = 0; @@ -382,7 +394,7 @@ protected: * \param s text stream to write the generated output * \param metaClass the class that should be generated */ - virtual void generateClass(QTextStream &s, GeneratorContext &classContext) = 0; + virtual void generateClass(QTextStream &s, const GeneratorContext &classContext) = 0; virtual bool finishGeneration() = 0; /** diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 7c9ce4fb2..3c9d13b48 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -33,6 +33,7 @@ #include <iostream> #include <apiextractor.h> #include <fileout.h> +#include <reporthandler.h> #include <typedatabase.h> #include <messages.h> #include "generator.h" @@ -59,10 +60,14 @@ static inline QString skipDeprecatedOption() { return QStringLiteral("skip-depre static const char helpHint[] = "Note: use --help or -h for more information.\n"; -using CommandArgumentMap = QMap<QString, QString>; - using OptionDescriptions = Generator::OptionDescriptions; +struct CommandLineArguments +{ + QMap<QString, QString> options; + QStringList positionalArguments; +}; + static void printOptions(QTextStream &s, const OptionDescriptions &options) { s.setFieldAlignment(QTextStream::AlignLeft); @@ -73,16 +78,16 @@ static void printOptions(QTextStream &s, const OptionDescriptions &options) if (od.second.isEmpty()) { s << ", "; } else { - s << endl; + s << Qt::endl; const auto lines = od.second.splitRef(QLatin1Char('\n')); for (const auto &line : lines) - s << " " << line << endl; - s << endl; + s << " " << line << Qt::endl; + s << Qt::endl; } } } -static bool processProjectFile(QFile &projectFile, QMap<QString, QString> &args) +static bool processProjectFile(QFile &projectFile, CommandLineArguments &args) { QByteArray line = projectFile.readLine().trimmed(); if (line.isEmpty() || line != "[generator-project]") @@ -123,36 +128,36 @@ static bool processProjectFile(QFile &projectFile, QMap<QString, QString> &args) else if (key == "api-version") apiVersions << value; else if (key == "header-file") - args.insert(QLatin1String("arg-1"), value); + args.positionalArguments.prepend(value); else if (key == "typesystem-file") - args.insert(QLatin1String("arg-2"), value); + args.positionalArguments.append(value); else - args.insert(QString::fromUtf8(key), value); + args.options.insert(QString::fromUtf8(key), value); } if (!includePaths.isEmpty()) - args.insert(includePathOption(), includePaths.join(pathSplitter)); + args.options.insert(includePathOption(), includePaths.join(pathSplitter)); if (!frameworkIncludePaths.isEmpty()) - args.insert(frameworkIncludePathOption(), - frameworkIncludePaths.join(pathSplitter)); + args.options.insert(frameworkIncludePathOption(), + frameworkIncludePaths.join(pathSplitter)); if (!systemIncludePaths.isEmpty()) { - args.insert(systemIncludePathOption(), - systemIncludePaths.join(pathSplitter)); + args.options.insert(systemIncludePathOption(), + systemIncludePaths.join(pathSplitter)); } if (!typesystemPaths.isEmpty()) - args.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter)); + args.options.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter)); if (!apiVersions.isEmpty()) - args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); + args.options.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); if (!languageLevel.isEmpty()) - args.insert(languageLevelOption(), languageLevel); + args.options.insert(languageLevelOption(), languageLevel); return true; } -static CommandArgumentMap getInitializedArguments() +static CommandLineArguments getProjectFileArguments() { - CommandArgumentMap args; + CommandLineArguments args; QStringList arguments = QCoreApplication::arguments(); QString appName = arguments.constFirst(); arguments.removeFirst(); @@ -194,22 +199,22 @@ static CommandArgumentMap getInitializedArguments() // Concatenate values of path arguments that can occur multiple times on the // command line. static void addPathOptionValue(const QString &option, const QString &value, - CommandArgumentMap &args) + CommandLineArguments &args) { - const CommandArgumentMap::iterator it = args.find(option); - if (it != args.end()) + auto it = args.options.find(option); + if (it != args.options.end()) it.value().append(pathSplitter + value); else - args.insert(option, value); + args.options.insert(option, value); } -static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &args) +static void getCommandLineArg(QString arg, int &argNum, CommandLineArguments &args) { if (arg.startsWith(QLatin1String("--"))) { arg.remove(0, 2); const int split = arg.indexOf(QLatin1Char('=')); if (split < 0) { - args.insert(arg, QString()); + args.options.insert(arg, QString()); return; } const QString option = arg.left(split); @@ -218,7 +223,7 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> & || option == systemIncludePathOption() || option == typesystemPathOption()) { addPathOptionValue(option, value, args); } else { - args.insert(option, value); + args.options.insert(option, value); } return; } @@ -233,28 +238,26 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> & else if (arg.startsWith(QLatin1Char('T'))) addPathOptionValue(typesystemPathOption(), arg.mid(1), args); else if (arg == QLatin1String("h")) - args.insert(helpOption(), QString()); + args.options.insert(helpOption(), QString()); else if (arg.startsWith(QLatin1String("std="))) - args.insert(languageLevelOption(), arg.mid(4)); + args.options.insert(languageLevelOption(), arg.mid(4)); else - args.insert(arg, QString()); + args.options.insert(arg, QString()); return; } - argNum++; - args.insert(QStringLiteral("arg-") + QString::number(argNum), arg); + if (argNum < args.positionalArguments.size()) + args.positionalArguments[argNum] = arg; + else + args.positionalArguments.append(arg); + ++argNum; } -static QMap<QString, QString> getCommandLineArgs() +static void getCommandLineArgs(CommandLineArguments &args) { - QMap<QString, QString> args = getInitializedArguments(); - QStringList arguments = QCoreApplication::arguments(); - arguments.removeFirst(); - + const QStringList arguments = QCoreApplication::arguments(); int argNum = 0; - for (const QString &carg : qAsConst(arguments)) - getCommandLineArg(carg.trimmed(), argNum, args); - - return args; + for (int i = 1, size = arguments.size(); i < size; ++i) + getCommandLineArg(arguments.at(i).trimmed(), argNum, args); } static inline Generators docGenerators() @@ -284,7 +287,7 @@ void printUsage() { QTextStream s(stdout); s << "Usage:\n " - << "shiboken [options] header-file typesystem-file\n\n" + << "shiboken [options] header-file(s) typesystem-file\n\n" << "General options:\n"; QString pathSyntax; QTextStream(&pathSyntax) << "<path>[" << pathSplitter << "<path>" @@ -343,7 +346,7 @@ void printUsage() for (const GeneratorPtr &generator : generators) { const OptionDescriptions options = generator->options(); if (!options.isEmpty()) { - s << endl << generator->name() << " options:\n\n"; + s << Qt::endl << generator->name() << " options:\n\n"; printOptions(s, generator->options()); } } @@ -364,14 +367,14 @@ static inline void errorPrint(const QString &s) } static void parseIncludePathOption(const QString &option, HeaderType headerType, - CommandArgumentMap &args, + CommandLineArguments &args, ApiExtractor &extractor) { - const CommandArgumentMap::iterator it = args.find(option); - if (it != args.end()) { + const auto it = args.options.find(option); + if (it != args.options.end()) { const QStringList includePathListList = - it.value().split(pathSplitter, QString::SkipEmptyParts); - args.erase(it); + it.value().split(pathSplitter, Qt::SkipEmptyParts); + args.options.erase(it); for (const QString &s : includePathListList) { auto path = QFile::encodeName(QDir::cleanPath(s)); extractor.addIncludePath(HeaderPath{path, headerType}); @@ -387,26 +390,29 @@ int main(int argc, char *argv[]) // needed by qxmlpatterns QCoreApplication app(argc, argv); ReportHandler::install(); - qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCInfo(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); // Store command arguments in a map - CommandArgumentMap args = getCommandLineArgs(); + const CommandLineArguments projectFileArguments = getProjectFileArguments(); + CommandLineArguments args = projectFileArguments; + getCommandLineArgs(args); Generators generators; - CommandArgumentMap::iterator ait = args.find(QLatin1String("version")); - if (ait != args.end()) { - args.erase(ait); + auto ait = args.options.find(QLatin1String("version")); + if (ait != args.options.end()) { + args.options.erase(ait); printVerAndBanner(); return EXIT_SUCCESS; } QString generatorSet; - ait = args.find(QLatin1String("generator-set")); - if (ait == args.end()) // Also check QLatin1String("generatorSet") command line argument for backward compatibility. - ait = args.find(QLatin1String("generatorSet")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("generator-set")); + if (ait == args.options.end()) // Also check QLatin1String("generatorSet") command line argument for backward compatibility. + ait = args.options.find(QLatin1String("generatorSet")); + if (ait != args.options.end()) { generatorSet = ait.value(); - args.erase(ait); + args.options.erase(ait); } // Pre-defined generator sets. @@ -423,30 +429,30 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - ait = args.find(QLatin1String("help")); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(QLatin1String("help")); + if (ait != args.options.end()) { + args.options.erase(ait); printUsage(); return EXIT_SUCCESS; } - ait = args.find(diffOption()); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(diffOption()); + if (ait != args.options.end()) { + args.options.erase(ait); FileOut::diff = true; } - ait = args.find(dryrunOption()); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(dryrunOption()); + if (ait != args.options.end()) { + args.options.erase(ait); FileOut::dummy = true; } QString licenseComment; - ait = args.find(QLatin1String("license-file")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("license-file")); + if (ait != args.options.end()) { QFile licenseFile(ait.value()); - args.erase(ait); + args.options.erase(ait); if (licenseFile.open(QIODevice::ReadOnly)) { licenseComment = QString::fromUtf8(licenseFile.readAll()); } else { @@ -457,10 +463,10 @@ int main(int argc, char *argv[]) } QString outputDirectory = QLatin1String("out"); - ait = args.find(QLatin1String("output-directory")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("output-directory")); + if (ait != args.options.end()) { outputDirectory = ait.value(); - args.erase(ait); + args.options.erase(ait); } if (!QDir(outputDirectory).exists()) { @@ -474,38 +480,35 @@ int main(int argc, char *argv[]) // Create and set-up API Extractor ApiExtractor extractor; extractor.setLogDirectory(outputDirectory); - ait = args.find(skipDeprecatedOption()); - if (ait != args.end()) { + ait = args.options.find(skipDeprecatedOption()); + if (ait != args.options.end()) { extractor.setSkipDeprecated(true); - args.erase(ait); + args.options.erase(ait); } - ait = args.find(QLatin1String("silent")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("silent")); + if (ait != args.options.end()) { extractor.setSilent(true); - args.erase(ait); + args.options.erase(ait); } else { - ait = args.find(QLatin1String("debug-level")); - if (ait != args.end()) { - const QString level = ait.value(); - args.erase(ait); - if (level == QLatin1String("sparse")) - extractor.setDebugLevel(ReportHandler::SparseDebug); - else if (level == QLatin1String("medium")) - extractor.setDebugLevel(ReportHandler::MediumDebug); - else if (level == QLatin1String("full")) - extractor.setDebugLevel(ReportHandler::FullDebug); + ait = args.options.find(QLatin1String("debug-level")); + if (ait != args.options.end()) { + if (!ReportHandler::setDebugLevelFromArg(ait.value())) { + errorPrint(QLatin1String("Invalid debug level: ") + ait.value()); + return EXIT_FAILURE; + } + args.options.erase(ait); } } - ait = args.find(QLatin1String("no-suppress-warnings")); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(QLatin1String("no-suppress-warnings")); + if (ait != args.options.end()) { + args.options.erase(ait); extractor.setSuppressWarnings(false); } - ait = args.find(QLatin1String("api-version")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("api-version")); + if (ait != args.options.end()) { const QStringList &versions = ait.value().split(QLatin1Char('|')); - args.erase(ait); + args.options.erase(ait); for (const QString &fullVersion : versions) { QStringList parts = fullVersion.split(QLatin1Char(',')); QString package; @@ -519,16 +522,16 @@ int main(int argc, char *argv[]) } } - ait = args.find(QLatin1String("drop-type-entries")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("drop-type-entries")); + if (ait != args.options.end()) { extractor.setDropTypeEntries(ait.value()); - args.erase(ait); + args.options.erase(ait); } - ait = args.find(QLatin1String("typesystem-paths")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("typesystem-paths")); + if (ait != args.options.end()) { extractor.addTypesystemSearchPath(ait.value().split(pathSplitter)); - args.erase(ait); + args.options.erase(ait); } parseIncludePathOption(includePathOption(), HeaderType::Standard, @@ -538,46 +541,44 @@ int main(int argc, char *argv[]) parseIncludePathOption(systemIncludePathOption(), HeaderType::System, args, extractor); - ait = args.find(QLatin1String("arg-1")); - if (ait == args.end()) { - errorPrint(QLatin1String("Required argument header-file is missing.")); - return EXIT_FAILURE; - } - const QString cppFileName = ait.value(); - args.erase(ait); - const QFileInfo cppFileNameFi(cppFileName); - if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) { - errorPrint(QLatin1Char('"') + cppFileName + QLatin1String("\" does not exist.")); + if (args.positionalArguments.size() < 2) { + errorPrint(QLatin1String("Insufficient positional arguments, specify header-file and typesystem-file.")); + std::cout << '\n'; + printUsage(); return EXIT_FAILURE; } - ait = args.find(QLatin1String("arg-2")); - if (ait == args.end()) { - errorPrint(QLatin1String("Required argument typesystem-file is missing.")); - return EXIT_FAILURE; - } - const QString typeSystemFileName = ait.value(); - args.erase(ait); + const QString typeSystemFileName = args.positionalArguments.takeLast(); QString messagePrefix = QFileInfo(typeSystemFileName).baseName(); if (messagePrefix.startsWith(QLatin1String("typesystem_"))) messagePrefix.remove(0, 11); ReportHandler::setPrefix(QLatin1Char('(') + messagePrefix + QLatin1Char(')')); + QFileInfoList cppFileNames; + for (const QString &cppFileName : qAsConst(args.positionalArguments)) { + const QFileInfo cppFileNameFi(cppFileName); + if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) { + errorPrint(QLatin1Char('"') + cppFileName + QLatin1String("\" does not exist.")); + return EXIT_FAILURE; + } + cppFileNames.append(cppFileNameFi); + } + // Pass option to all generators (Cpp/Header generator have the same options) - for (ait = args.begin(); ait != args.end(); ) { + for (ait = args.options.begin(); ait != args.options.end(); ) { bool found = false; for (const GeneratorPtr &generator : qAsConst(generators)) found |= generator->handleOption(ait.key(), ait.value()); if (found) - ait = args.erase(ait); + ait = args.options.erase(ait); else ++ait; } - ait = args.find(languageLevelOption()); - if (ait != args.end()) { + ait = args.options.find(languageLevelOption()); + if (ait != args.options.end()) { const QByteArray languageLevelBA = ait.value().toLatin1(); - args.erase(ait); + args.options.erase(ait); const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData()); if (level == LanguageLevel::Default) { std::cout << "Invalid argument for language level: \"" @@ -591,13 +592,14 @@ int main(int argc, char *argv[]) * --project-file, also the arguments of each generator before * checking if there isn't any existing arguments in argsHandler. */ - args.remove(QLatin1String("project-file")); - CommandArgumentMap projectFileArgs = getInitializedArguments(); - for (auto it = projectFileArgs.cbegin(), end = projectFileArgs.cend(); it != end; ++it) - args.remove(it.key()); + args.options.remove(QLatin1String("project-file")); + for (auto it = projectFileArguments.options.cbegin(), end = projectFileArguments.options.cend(); + it != end; ++it) { + args.options.remove(it.key()); + } - if (!args.isEmpty()) { - errorPrint(msgLeftOverArguments(args)); + if (!args.options.isEmpty()) { + errorPrint(msgLeftOverArguments(args.options)); std::cout << helpHint; return EXIT_FAILURE; } @@ -607,7 +609,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - extractor.setCppFileName(cppFileNameFi.absoluteFilePath()); + extractor.setCppFileNames(cppFileNames); extractor.setTypeSystem(typeSystemFileName); if (!extractor.run()) { @@ -618,8 +620,11 @@ int main(int argc, char *argv[]) if (!extractor.classCount()) qCWarning(lcShiboken) << "No C++ classes found!"; - qCDebug(lcShiboken) << extractor << '\n' - << *TypeDatabase::instance(); + if (ReportHandler::isDebug(ReportHandler::FullDebug) + || qEnvironmentVariableIsSet("SHIBOKEN_DUMP_CODEMODEL")) { + qCInfo(lcShiboken) << "API Extractor:\n" << extractor + << "\n\nType datase:\n" << *TypeDatabase::instance(); + } for (const GeneratorPtr &g : qAsConst(generators)) { g->setOutputDirectory(outputDirectory); @@ -635,7 +640,6 @@ int main(int argc, char *argv[]) } const QByteArray doneMessage = ReportHandler::doneMessage(); - qCDebug(lcShiboken, "%s", doneMessage.constData()); std::cout << doneMessage.constData() << std::endl; return EXIT_SUCCESS; diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index f4efc293f..014cc948e 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -172,7 +172,7 @@ static QChar lastChar(const QTextStream &str) static QTextStream &ensureEndl(QTextStream &s) { if (lastChar(s) != QLatin1Char('\n')) - s << endl; + s << Qt::endl; return s; } @@ -478,7 +478,7 @@ QString QtXmlToSphinx::transform(const QString& doc) << reader.errorString() << " at " << reader.lineNumber() << ':' << reader.columnNumber() << '\n' << doc; m_output << INDENT << message; - qCWarning(lcShiboken).noquote().nospace() << message; + qCWarning(lcShibokenDoc).noquote().nospace() << message; break; } @@ -502,10 +502,10 @@ QString QtXmlToSphinx::transform(const QString& doc) if (!m_inlineImages.isEmpty()) { // Write out inline image definitions stored in handleInlineImageTag(). - m_output << endl; + m_output << Qt::endl; for (const InlineImage &img : qAsConst(m_inlineImages)) - m_output << ".. |" << img.tag << "| image:: " << img.href << endl; - m_output << endl; + m_output << ".. |" << img.tag << "| image:: " << img.href << Qt::endl; + m_output << Qt::endl; m_inlineImages.clear(); } @@ -541,7 +541,7 @@ QString QtXmlToSphinx::readFromLocations(const QStringList &locations, const QSt << locations.join(QLatin1String("\", \"")); return QString(); // null } - qCDebug(lcShiboken).noquote().nospace() << "snippet file " << path + qCDebug(lcShibokenDoc).noquote().nospace() << "snippet file " << path << " [" << identifier << ']' << " resolved to " << resolvedPath; return readFromLocation(resolvedPath, identifier, errorMessage); } @@ -608,11 +608,11 @@ void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) else type = types[typeIdx]; } else if (token == QXmlStreamReader::EndElement) { - m_output << Pad(type, headingSize) << endl << endl; + m_output << Pad(type, headingSize) << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; headingSize = writeEscapedRstText(m_output, reader.text().trimmed()); - m_output << endl; + m_output << Qt::endl; } } @@ -628,7 +628,7 @@ void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) else if (result.startsWith(QLatin1String("**Note:**"))) result.replace(0, 9, QLatin1String(".. note:: ")); - m_output << INDENT << result << endl << endl; + m_output << INDENT << result << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { const QStringRef text = reader.text(); const QChar end = lastChar(m_output); @@ -726,7 +726,7 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) handleLinkEnd(m_seeAlsoContext.data()); m_seeAlsoContext.reset(); } - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; break; default: break; @@ -747,7 +747,7 @@ void formatSnippet(QTextStream &str, Indent indent, const QString &snippet) for (const QStringRef &line : lines) { if (!line.trimmed().isEmpty()) str << indent << line; - str << endl; + str << Qt::endl; } } @@ -783,7 +783,7 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) const QString pythonCode = readFromLocations(m_generator->codeSnippetDirs(), location, identifier, &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); // Fall back to C++ snippet when "path" attribute is present. // Also read fallback snippet when comparison is desired. QString fallbackCode; @@ -792,15 +792,15 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) const QString fallback = reader.attributes().value(fallbackPathAttribute()).toString(); if (QFileInfo::exists(fallback)) { if (pythonCode.isEmpty()) - qCWarning(lcShiboken, "%s", qPrintable(msgFallbackWarning(reader, m_context, m_lastTagName, location, identifier, fallback))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgFallbackWarning(reader, m_context, m_lastTagName, location, identifier, fallback))); fallbackCode = readFromLocation(fallback, identifier, &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); } } if (!pythonCode.isEmpty() && !fallbackCode.isEmpty() && snippetComparison()) - qCDebug(lcShiboken, "%s", qPrintable(msgSnippetComparison(location, identifier, pythonCode, fallbackCode))); + qCDebug(lcShibokenDoc, "%s", qPrintable(msgSnippetComparison(location, identifier, pythonCode, fallbackCode))); if (!consecutiveSnippet) m_output << INDENT << "::\n\n"; @@ -811,7 +811,7 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>\n"; else formatSnippet(m_output, INDENT, code); - m_output << endl; + m_output << Qt::endl; } } void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) @@ -930,16 +930,16 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) switch (listType) { case BulletList: case OrderedList: { - m_output << endl; + m_output << Qt::endl; const char *separator = listType == BulletList ? "* " : "#. "; const char *indent = listType == BulletList ? " " : " "; for (const TableCell &cell : m_currentTable.constFirst()) { const QVector<QStringRef> itemLines = cell.data.splitRef(QLatin1Char('\n')); - m_output << INDENT << separator << itemLines.constFirst() << endl; + m_output << INDENT << separator << itemLines.constFirst() << Qt::endl; for (int i = 1, max = itemLines.count(); i < max; ++i) - m_output << INDENT << indent << itemLines[i] << endl; + m_output << INDENT << indent << itemLines[i] << Qt::endl; } - m_output << endl; + m_output << Qt::endl; } break; case EnumeratedList: @@ -1120,7 +1120,7 @@ static bool copyImage(const QString &href, const QString &docDataDir, << source.errorString(); return false; } - qCDebug(lcShiboken()).noquote().nospace() << __FUNCTION__ << " href=\"" + qCDebug(lcShibokenDoc()).noquote().nospace() << __FUNCTION__ << " href=\"" << href << "\", context=\"" << context << "\", docDataDir=\"" << docDataDir << "\", outputDir=\"" << outputDir << "\", copied \"" << source.fileName() << "\"->\"" << targetFileName << '"'; @@ -1134,7 +1134,7 @@ bool QtXmlToSphinx::copyImage(const QString &href) const ::copyImage(href, m_generator->docDataDir(), m_context, m_generator->outputDirectory(), &errorMessage); if (!result) - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return result; } @@ -1144,7 +1144,7 @@ void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) return; const QString href = reader.attributes().value(QLatin1String("href")).toString(); if (copyImage(href)) - m_output << INDENT << ".. image:: " << href << endl << endl; + m_output << INDENT << ".. image:: " << href << Qt::endl << Qt::endl; } void QtXmlToSphinx::handleInlineImageTag(QXmlStreamReader& reader) @@ -1174,13 +1174,13 @@ void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { QString format = reader.attributes().value(QLatin1String("format")).toString(); - m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; + m_output << INDENT << ".. raw:: " << format.toLower() << Qt::endl << Qt::endl; } else if (token == QXmlStreamReader::Characters) { const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); for (const QStringRef &row : lst) - m_output << INDENT << INDENT << row << endl; + m_output << INDENT << INDENT << row << Qt::endl; } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; } } @@ -1193,9 +1193,9 @@ void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) } else if (token == QXmlStreamReader::Characters) { const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); for (const QStringRef &row : lst) - m_output << INDENT << INDENT << row << endl; + m_output << INDENT << INDENT << row << Qt::endl; } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; + m_output << Qt::endl << Qt::endl; INDENT.indent--; } } @@ -1204,7 +1204,7 @@ void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader) { QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) - qCDebug(lcShiboken).noquote().nospace() << "Unknown QtDoc tag: \"" << reader.name().toString() << "\"."; + qCDebug(lcShibokenDoc).noquote().nospace() << "Unknown QtDoc tag: \"" << reader.name().toString() << "\"."; } void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader) @@ -1235,7 +1235,7 @@ void QtXmlToSphinx::handlePageTag(QXmlStreamReader &reader) ? writeEscapedRstText(m_output, title) : writeEscapedRstText(m_output, fullTitle); - m_output << endl << Pad('*', size) << endl << endl; + m_output << Qt::endl << Pad('*', size) << Qt::endl << Qt::endl; } void QtXmlToSphinx::handleTargetTag(QXmlStreamReader &reader) @@ -1292,14 +1292,14 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) QString errorMessage; QString code = readFromLocation(location, QString(), &errorMessage); if (!errorMessage.isEmpty()) - qCWarning(lcShiboken(), "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); + qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); m_output << INDENT << "::\n\n"; Indentation indentation(INDENT); if (code.isEmpty()) m_output << INDENT << "<Code snippet \"" << location << "\" not found>\n"; else formatCode(m_output, code, INDENT); - m_output << endl; + m_output << Qt::endl; } } @@ -1391,7 +1391,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const return; if (!isNormalized()) { - qCDebug(lcShiboken) << "Attempt to print an unnormalized table!"; + qCDebug(lcShibokenDoc) << "Attempt to print an unnormalized table!"; return; } @@ -1435,7 +1435,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const c = '-'; s << Pad(c, colWidths.at(col)) << '+'; } - s << endl; + s << Qt::endl; // Print the table cells @@ -1452,7 +1452,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const else s << ' '; if (rowLine < rowLines.count()) - s << qSetFieldWidth(colWidths[j]) << left << rowLines.at(rowLine) << qSetFieldWidth(0); + s << qSetFieldWidth(colWidths[j]) << Qt::left << rowLines.at(rowLine) << qSetFieldWidth(0); else s << Pad(' ', colWidths.at(j)); } @@ -1461,7 +1461,7 @@ void QtXmlToSphinx::Table::format (QTextStream& s) const s << "|\n"; } } - s << INDENT << horizontalLine << endl << endl; + s << INDENT << horizontalLine << Qt::endl << Qt::endl; } static QString getFuncName(const AbstractMetaFunction* cppFunc) { @@ -1523,7 +1523,7 @@ bool QtDocGenerator::shouldGenerate(const AbstractMetaClass *cls) const && cls->typeEntry()->type() != TypeEntry::SmartPointerType; } -QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const +QString QtDocGenerator::fileNameForContext(const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); if (!context.forSmartPointer()) { @@ -1562,11 +1562,11 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc s << INDENT << (typesystemIndentation > 0 && typesystemIndentation < line.size() ? line.right(line.size() - typesystemIndentation) : line) - << endl; + << Qt::endl; } } - s << endl; + s << Qt::endl; } static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) @@ -1584,7 +1584,7 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl QStringList classes; for (AbstractMetaClass *c : qAsConst(res)) classes << QLatin1String(":ref:`") + getClassTargetFullName(c, false) + QLatin1Char('`'); - s << classes.join(QLatin1String(", ")) << endl << endl; + s << classes.join(QLatin1String(", ")) << Qt::endl << Qt::endl; } // Extract the <brief> section from a WebXML (class) documentation and remove it @@ -1611,10 +1611,10 @@ static bool extractBrief(Documentation *sourceDoc, Documentation *brief) return true; } -void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +void QtDocGenerator::generateClass(QTextStream &s, const GeneratorContext &classContext) { - AbstractMetaClass *metaClass = classContext.metaClass(); - qCDebug(lcShiboken).noquote().nospace() << "Generating Documentation for " << metaClass->fullName(); + const AbstractMetaClass *metaClass = classContext.metaClass(); + qCDebug(lcShibokenDoc).noquote().nospace() << "Generating Documentation for " << metaClass->fullName(); m_packages[metaClass->package()] << fileNameForContext(classContext); @@ -1625,15 +1625,15 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex s << ".. _" << className << ":" << "\n\n"; s << ".. currentmodule:: " << metaClass->package() << "\n\n\n"; - s << className << endl; - s << Pad('*', className.count()) << endl << endl; + s << className << Qt::endl; + s << Pad('*', className.count()) << Qt::endl << Qt::endl; auto documentation = metaClass->documentation(); Documentation brief; if (extractBrief(&documentation, &brief)) writeFormattedText(s, brief, metaClass); - s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << endl + s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << Qt::endl << " :parts: 2\n\n"; // TODO: This would be a parameter in the future... @@ -1740,17 +1740,17 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions) { if (!functions.isEmpty()) { - s << title << endl - << QString(title.size(), QLatin1Char('^')) << endl; + s << title << Qt::endl + << QString(title.size(), QLatin1Char('^')) << Qt::endl; std::sort(functions.begin(), functions.end()); s << ".. container:: function_list\n\n"; Indentation indentation(INDENT); for (const QString &func : qAsConst(functions)) - s << INDENT << '*' << ' ' << func << endl; + s << INDENT << '*' << ' ' << func << Qt::endl; - s << endl << endl; + s << Qt::endl << Qt::endl; } } @@ -1760,7 +1760,7 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas const AbstractMetaEnumList &enums = cppClass->enums(); for (AbstractMetaEnum *en : enums) { - s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; + s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << Qt::endl << Qt::endl; writeFormattedText(s, en->documentation(), cppClass); const auto version = versionOf(en->typeEntry()); if (!version.isNull()) @@ -1775,7 +1775,7 @@ void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppCla const AbstractMetaFieldList &fields = cppClass->fields(); for (AbstractMetaField *field : fields) { - s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl; + s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << Qt::endl << Qt::endl; //TODO: request for member ‘documentation’ is ambiguous writeFormattedText(s, field->AbstractMetaAttributes::documentation(), cppClass); } @@ -1819,14 +1819,14 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* } } - s << endl; + s << Qt::endl; for (QHash<QString, AbstractMetaArgument*>::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { Indentation indentation(INDENT, 2); writeParameterType(s, cppClass, it.value()); } - s << endl; + s << Qt::endl; for (AbstractMetaFunction *func : qAsConst(lst)) writeFormattedText(s, func->documentation(), cppClass); @@ -1917,7 +1917,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, if (row.trimmed().size() == 0) { if (currentRow == 0) continue; - s << endl; + s << Qt::endl; } if (currentRow == 0) { @@ -1931,7 +1931,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, break; } } - s << row.midRef(offset) << endl; + s << row.midRef(offset) << Qt::endl; currentRow++; } @@ -1971,7 +1971,7 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, } } - s << endl; + s << Qt::endl; // TODO: Deprecate the use of doc string on glue code. // This is pre "add-function" and "inject-documentation" tags. @@ -2046,13 +2046,13 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, cons void QtDocGenerator::writeParameterType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) { s << INDENT << ":param " << arg->name() << ": " - << translateToPythonType(arg->type(), cppClass) << endl; + << translateToPythonType(arg->type(), cppClass) << Qt::endl; } void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func) { - s << endl; + s << Qt::endl; const AbstractMetaArgumentList &funcArgs = func->arguments(); for (AbstractMetaArgument *arg : funcArgs) { @@ -2078,9 +2078,9 @@ void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractM if (retType.isEmpty()) retType = translateToPythonType(func->type(), cppClass); - s << INDENT << ":rtype: " << retType << endl; + s << INDENT << ":rtype: " << retType << Qt::endl; } - s << endl; + s << Qt::endl; } void QtDocGenerator::writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, @@ -2134,7 +2134,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 std::sort(it.value().begin(), it.value().end()); if (i) - ss << endl; + ss << Qt::endl; ss << "**" << it.key() << "**\n\n"; i += 2; // a letter title is equivalent to two entries in space @@ -2184,11 +2184,11 @@ void QtDocGenerator::writeModuleDocumentation() FileOut output(outputDir + QLatin1String("/index.rst")); QTextStream& s = output.stream; - s << ".. module:: " << it.key() << endl << endl; + s << ".. module:: " << it.key() << Qt::endl << Qt::endl; const QString &title = it.key(); - s << title << endl; - s << Pad('*', title.length()) << endl << endl; + s << title << Qt::endl; + s << Pad('*', title.length()) << Qt::endl << Qt::endl; /* Avoid showing "Detailed Description for *every* class in toc tree */ Indentation indentation(INDENT); @@ -2202,7 +2202,7 @@ void QtDocGenerator::writeModuleDocumentation() if (!m_extraSectionDir.isEmpty()) { QDir extraSectionDir(m_extraSectionDir); if (!extraSectionDir.exists()) - qCWarning(lcShiboken) << m_extraSectionDir << "doesn't exist"; + qCWarning(lcShibokenDoc) << m_extraSectionDir << "doesn't exist"; QStringList fileList = extraSectionDir.entryList(QStringList() << (moduleName.mid(lastIndex + 1) + QLatin1String("?*.rst")), QDir::Files); QStringList::iterator it2 = fileList.begin(); @@ -2213,7 +2213,7 @@ void QtDocGenerator::writeModuleDocumentation() if (QFile::exists(newFilePath)) QFile::remove(newFilePath); if (!QFile::copy(m_extraSectionDir + QLatin1Char('/') + origFileName, newFilePath)) { - qCDebug(lcShiboken).noquote().nospace() << "Error copying extra doc " + qCDebug(lcShibokenDoc).noquote().nospace() << "Error copying extra doc " << QDir::toNativeSeparators(m_extraSectionDir + QLatin1Char('/') + origFileName) << " to " << QDir::toNativeSeparators(newFilePath); } @@ -2230,8 +2230,8 @@ void QtDocGenerator::writeModuleDocumentation() Indentation deeperIndentation(INDENT); s << INDENT << ":maxdepth: 1\n\n"; for (const QString &className : qAsConst(it.value())) - s << INDENT << className << endl; - s << endl << endl; + s << INDENT << className << Qt::endl; + s << Qt::endl << Qt::endl; } s << "Detailed Description\n--------------------\n\n"; @@ -2269,7 +2269,7 @@ void QtDocGenerator::writeAdditionalDocumentation() { QFile additionalDocumentationFile(m_additionalDocumentationList); if (!additionalDocumentationFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - qCWarning(lcShiboken, "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotOpenForReading(additionalDocumentationFile))); return; } @@ -2295,7 +2295,7 @@ void QtDocGenerator::writeAdditionalDocumentation() targetDir = outDir.absolutePath(); } else { if (!outDir.exists(dir) && !outDir.mkdir(dir)) { - qCWarning(lcShiboken, "Cannot create directory %s under %s", + qCWarning(lcShibokenDoc, "Cannot create directory %s under %s", qPrintable(dir), qPrintable(QDir::toNativeSeparators(outputDirectory()))); break; @@ -2312,14 +2312,14 @@ void QtDocGenerator::writeAdditionalDocumentation() if (QtXmlToSphinx::convertToRst(this, fi.absoluteFilePath(), rstFile, context, &errorMessage)) { ++successCount; - qCDebug(lcShiboken).nospace().noquote() << __FUNCTION__ + qCDebug(lcShibokenDoc).nospace().noquote() << __FUNCTION__ << " converted " << fi.fileName() << ' ' << rstFileName; } else { - qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); } } else { - qCWarning(lcShiboken, "%s", + qCWarning(lcShibokenDoc, "%s", qPrintable(msgNonExistentAdditionalDocFile(m_docDataDir, line))); } ++count; @@ -2327,7 +2327,7 @@ void QtDocGenerator::writeAdditionalDocumentation() } additionalDocumentationFile.close(); - qCInfo(lcShiboken, "Created %d/%d additional documentation files.", + qCInfo(lcShibokenDoc, "Created %d/%d additional documentation files.", successCount, count); } @@ -2346,7 +2346,7 @@ bool QtDocGenerator::doSetup() m_docParser = new QtDocParser; if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) { - qCWarning(lcShiboken) << "Documentation data dir and/or Qt source dir not informed, " + qCWarning(lcShibokenDoc) << "Documentation data dir and/or Qt source dir not informed, " "documentation will not be extracted from Qt sources."; return false; } @@ -2395,7 +2395,7 @@ bool QtDocGenerator::handleOption(const QString &key, const QString &value) return true; } if (key == QLatin1String("doc-parser")) { - qCDebug(lcShiboken).noquote().nospace() << "doc-parser: " << value; + qCDebug(lcShibokenDoc).noquote().nospace() << "doc-parser: " << value; if (value == QLatin1String("doxygen")) m_docParser = new DoxygenParser; return true; diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index 56cb9c4bb..e4067cc6f 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -238,8 +238,8 @@ public: protected: bool shouldGenerate(const AbstractMetaClass *) const override; QString fileNameSuffix() const override; - QString fileNameForContext(GeneratorContext &context) const override; - void generateClass(QTextStream &s, GeneratorContext &classContext) override; + QString fileNameForContext(const GeneratorContext &context) const override; + void generateClass(QTextStream &s, const GeneratorContext &classContext) override; bool finishGeneration() override; void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const override {} diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 64467e3d1..7b74c90d1 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -44,8 +44,7 @@ #include <QMetaType> #include <algorithm> - -#include <algorithm> +#include <cstring> static const char CPP_ARG0[] = "cppArg0"; @@ -196,7 +195,7 @@ QString CppGenerator::fileNameSuffix() const return QLatin1String("_wrapper.cpp"); } -QString CppGenerator::fileNameForContext(GeneratorContext &context) const +QString CppGenerator::fileNameForContext(const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); if (!context.forSmartPointer()) { @@ -293,14 +292,12 @@ static inline bool canGenerateFieldSetter(const AbstractMetaField *field) \param s the output buffer \param metaClass the pointer to metaclass information */ -void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classContext) { - AbstractMetaClass *metaClass = classContext.metaClass(); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName(); + const AbstractMetaClass *metaClass = classContext.metaClass(); // write license comment - s << licenseComment() << endl; + s << licenseComment() << Qt::endl; if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { s << "//workaround to access protected functions\n"; @@ -315,7 +312,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "#include <pysidesignal.h>\n" << "#include <pysideproperty.h>\n" << "#include <pyside.h>\n" - << "#include <destroylistener.h>\n" + << "#include <pysideqenum.h>\n" << "#include <qapp_macro.h>\n\n" << "QT_WARNING_DISABLE_DEPRECATED\n\n"; } @@ -332,6 +329,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "#include <algorithm>\n#include <set>\n"; if (metaClass->generateExceptionHandling()) s << "#include <exception>\n"; + s << "#include <iterator>\n"; // For containers + + if (wrapperDiagnostics()) + s << "#include <helper.h>\n#include <iostream>\n"; s << "\n// module include\n" << "#include \"" << getModuleHeaderFileName() << "\"\n"; @@ -339,11 +340,11 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); s << "\n// main header\n" << "#include \"" << headerfile << "\"\n"; - s << endl << "// inner classes\n"; + s << Qt::endl << "// inner classes\n"; const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); for (AbstractMetaClass *innerClass : innerClasses) { - GeneratorContext innerClassContext(innerClass); - if (shouldGenerate(innerClass)) { + GeneratorContext innerClassContext = contextForClass(innerClass); + if (shouldGenerate(innerClass) && !innerClass->typeEntry()->isSmartPointer()) { QString headerfile = fileNameForContext(innerClassContext); headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); s << "#include \"" << headerfile << "\"\n"; @@ -361,8 +362,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) includes.append(cppEnum->typeEntry()->extraIncludes()); std::sort(includes.begin(), includes.end()); for (const Include &inc : qAsConst(includes)) - s << inc.toString() << endl; - s << endl; + s << inc.toString() << Qt::endl; + s << Qt::endl; s << "\n#include <cctype>\n#include <cstring>\n"; @@ -381,7 +382,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } } - s << endl << endl << typeNameFunc << endl; + s << Qt::endl << Qt::endl << typeNameFunc << Qt::endl; // Create string literal for smart pointer getter method. if (classContext.forSmartPointer()) { @@ -394,21 +395,23 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) // class inject-code native/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass); - s << endl; + writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), + TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, + classContext); + s << Qt::endl; } // python conversion rules if (metaClass->typeEntry()->hasTargetConversionRule()) { s << "// Python Conversion\n"; - s << metaClass->typeEntry()->conversionRule() << endl; + s << metaClass->typeEntry()->conversionRule() << Qt::endl; } - if (shouldGenerateCppWrapper(metaClass)) { + if (classContext.useWrapper()) { s << "// Native ---------------------------------------------------------\n\n"; if (avoidProtectedHack() && usePySideExtensions()) { - s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n"; + s << "void " << classContext.wrapperName() << "::pysideInitQtMetaTypes()\n{\n"; Indentation indent(INDENT); writeInitQtMetaTypeFunctionBody(s, classContext); s << "}\n\n"; @@ -416,22 +419,22 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); int maxOverrides = 0; - writeCacheResetNative(s, metaClass); + writeCacheResetNative(s, classContext); for (const AbstractMetaFunction *func : funcs) { const bool notAbstract = !func->isAbstract(); if ((func->isPrivate() && notAbstract && !visibilityModifiedToPrivate(func)) || (func->isModifiedRemoved() && notAbstract)) continue; if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) - writeConstructorNative(s, func); + writeConstructorNative(s, classContext, func); else if (shouldWriteVirtualMethodNative(func)) writeVirtualMethodNative(s, func, maxOverrides++); } if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) { if (usePySideExtensions() && metaClass->isQObject()) - writeMetaObjectMethod(s, metaClass); - writeDestructorNative(s, metaClass); + writeMetaObjectMethod(s, classContext); + writeDestructorNative(s, classContext); } } @@ -553,7 +556,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) // Write methods definition s << "static PyMethodDef " << className << "_methods[] = {\n"; - s << methodsDefinitions << endl; + s << methodsDefinitions << Qt::endl; if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { s << INDENT << "{\"__copy__\", reinterpret_cast<PyCFunction>(" << className << "___copy__)" << ", METH_NOARGS},\n"; @@ -580,9 +583,9 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeCppSelfDefinition(s, classContext); if (f->allowThread()) { s << INDENT << "int result;\n"; - s << INDENT << BEGIN_ALLOW_THREADS << endl; + s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl; s << INDENT << "result = !" << CPP_SELF_VAR << "->isNull();\n"; - s << INDENT << END_ALLOW_THREADS << endl; + s << INDENT << END_ALLOW_THREADS << Qt::endl; s << INDENT << "return result;\n"; } else { s << INDENT << "return !" << CPP_SELF_VAR << "->isNull();\n"; @@ -635,10 +638,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeGetterFunction(s, metaField, classContext); if (canGenerateFieldSetter(metaField)) writeSetterFunction(s, metaField, classContext); - s << endl; + s << Qt::endl; } - s << "// Getters and Setters for " << metaClass->name() << endl; + s << "// Getters and Setters for " << metaClass->name() << Qt::endl; s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {\n"; for (const AbstractMetaField *metaField : fields) { if (metaField->isStatic()) @@ -666,7 +669,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeTpClearFunction(s, metaClass); writeClassDefinition(s, metaClass, classContext); - s << endl; + s << Qt::endl; if (metaClass->isPolymorphic() && metaClass->baseClass()) writeTypeDiscoveryFunction(s, metaClass); @@ -680,37 +683,44 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) if (hasFlags) { writeFlagsMethods(s, cppEnum); writeFlagsNumberMethodsDefinition(s, cppEnum); - s << endl; + s << Qt::endl; } } - s << endl; + s << Qt::endl; writeConverterFunctions(s, metaClass, classContext); writeClassRegister(s, metaClass, classContext, signatureStream); // class inject-code native/end if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, metaClass); - s << endl; + writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), + TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, + classContext); + s << Qt::endl; } } -void CppGenerator::writeCacheResetNative(QTextStream &s, const AbstractMetaClass *metaClass) +void CppGenerator::writeCacheResetNative(QTextStream &s, const GeneratorContext &classContext) { Indentation indentation(INDENT); - s << "void " << wrapperName(metaClass) << "::resetPyMethodCache()\n{\n"; + s << "void " << classContext.wrapperName() + << "::resetPyMethodCache()\n{\n"; s << INDENT << "std::fill_n(m_PyMethodCache, sizeof(m_PyMethodCache) / sizeof(m_PyMethodCache[0]), false);\n"; s << "}\n\n"; } -void CppGenerator::writeConstructorNative(QTextStream &s, const AbstractMetaFunction *func) +void CppGenerator::writeConstructorNative(QTextStream &s, const GeneratorContext &classContext, + const AbstractMetaFunction *func) { Indentation indentation(INDENT); - s << functionSignature(func, wrapperName(func->ownerClass()) + QLatin1String("::"), QString(), + const QString qualifiedName = classContext.wrapperName() + QLatin1String("::"); + s << functionSignature(func, qualifiedName, QString(), OriginalTypeDescription | SkipDefaultValues); s << " : "; writeFunctionCall(s, func); s << "\n{\n"; + if (wrapperDiagnostics()) + s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << this << '\n';)" << '\n'; const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); s << INDENT << "resetPyMethodCache();\n"; writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); @@ -719,10 +729,13 @@ void CppGenerator::writeConstructorNative(QTextStream &s, const AbstractMetaFunc s << "}\n\n"; } -void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass) +void CppGenerator::writeDestructorNative(QTextStream &s, const GeneratorContext &classContext) { Indentation indentation(INDENT); - s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()\n{\n"; + s << classContext.wrapperName() << "::~" + << classContext.wrapperName() << "()\n{\n"; + if (wrapperDiagnostics()) + s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << this << '\n';)" << '\n'; // kill pyobject s << INDENT << "SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);\n"; s << INDENT << "Shiboken::Object::destroy(wrapper, this);\n"; @@ -750,11 +763,14 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"'); // SbkType would return null when the type is a container. - if (func->type()->typeEntry()->isContainer()) { + auto typeEntry = func->type()->typeEntry(); + if (typeEntry->isContainer()) { return QLatin1Char('"') - + reinterpret_cast<const ContainerTypeEntry *>(func->type()->typeEntry())->typeName() + + reinterpret_cast<const ContainerTypeEntry *>(typeEntry)->typeName() + QLatin1Char('"'); } + if (typeEntry->isSmartPointer()) + return QLatin1Char('"') + typeEntry->qualifiedCppName() + QLatin1Char('"'); if (avoidProtectedHack()) { const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(func->type()); @@ -765,7 +781,8 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio if (func->type()->isPrimitive()) return QLatin1Char('"') + func->type()->name() + QLatin1Char('"'); - return QString::fromLatin1("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< %1 >())->tp_name").arg(func->type()->typeEntry()->qualifiedCppName()); + return QLatin1String("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< ") + + typeEntry->qualifiedCppName() + QLatin1String(" >())->tp_name"); } void CppGenerator::writeVirtualMethodNative(QTextStream &s, @@ -821,7 +838,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, errorMsg += func->signature(); errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); qCWarning(lcShiboken).noquote().nospace() << errorMsg; - s << endl << INDENT << "#error " << errorMsg << endl; + s << Qt::endl << INDENT << "#error " << errorMsg << Qt::endl; } } else { defaultReturnExpr.setType(DefaultValue::Void); @@ -832,7 +849,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, << QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\ "completely removed on type system.") .arg(func->ownerClass()->name(), func->minimalSignature()); - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; s << "}\n\n"; return; } @@ -842,11 +859,19 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, CodeSnipList snips = func->injectedCodeSnips(); const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg); - s << endl; } // PYSIDE-803: Build a boolean cache for unused overrides. bool multi_line = retType == nullptr; // set to true when using instrumentation + if (wrapperDiagnostics()) { + s << INDENT << "std::cerr << "; +#ifndef Q_CC_MSVC // g++ outputs __FUNCTION__ unqualified + s << '"' << prefix << R"(" << )"; +#endif + s << R"(__FUNCTION__ << ' ' << this << " m_PyMethodCache[" << )" + << cacheIndex << R"( << "]=" << m_PyMethodCache[)" << cacheIndex + << R"(] << '\n';)" << '\n'; + } s << INDENT << "if (m_PyMethodCache[" << cacheIndex << "])" << (multi_line ? " {\n" : "\n"); { Indentation indentation(INDENT); @@ -873,7 +898,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, s << INDENT << "if (PyErr_Occurred())\n"; { Indentation indentation(INDENT); - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR << "(Shiboken::BindingManager::instance().getOverride(this, \""; @@ -887,7 +912,6 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, snips = func->injectedCodeSnips(); const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg); - s << endl; } if (func->isAbstract()) { @@ -962,7 +986,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\",\n"; - s << argConversions.join(QLatin1String(",\n")) << endl; + s << argConversions.join(QLatin1String(",\n")) << Qt::endl; s << INDENT << "));\n"; } @@ -980,7 +1004,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } } } - s << endl; + s << Qt::endl; CodeSnipList snips; if (func->hasInjectedCode()) { @@ -991,7 +1015,6 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); - s << endl; } if (!injectedCodeCallsPythonOverride(func)) { @@ -1004,7 +1027,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, { Indentation indent(INDENT); s << INDENT << "PyErr_Print();\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1026,7 +1049,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"Invalid return value in function %s, expected %s, got %s.\", \""; s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1047,7 +1070,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"Invalid return value in function %s, expected %s, got %s.\", \""; s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl; + s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; } s << INDENT << "}\n"; @@ -1090,7 +1113,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, } if (func->hasInjectedCode()) { - s << endl; + s << Qt::endl; const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); } @@ -1116,16 +1139,17 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, s<< "}\n\n"; } -void CppGenerator::writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass *metaClass) +void CppGenerator::writeMetaObjectMethod(QTextStream &s, const GeneratorContext &classContext) { Indentation indentation(INDENT); - QString wrapperClassName = wrapperName(metaClass); + const QString wrapperClassName = classContext.wrapperName(); + const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName(); s << "const QMetaObject *" << wrapperClassName << "::metaObject() const\n{\n"; s << INDENT << "if (QObject::d_ptr->metaObject)\n" << INDENT << INDENT << "return QObject::d_ptr->dynamicMetaObject();\n"; s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n"; s << INDENT << "if (pySelf == nullptr)\n"; - s << INDENT << INDENT << "return " << metaClass->qualifiedCppName() << "::metaObject();\n"; + s << INDENT << INDENT << "return " << qualifiedCppName << "::metaObject();\n"; s << INDENT << "return PySide::SignalManager::retrieveMetaObject(reinterpret_cast<PyObject *>(pySelf));\n"; s<< "}\n\n"; @@ -1134,7 +1158,8 @@ void CppGenerator::writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass s << "{\n"; AbstractMetaFunction *func = nullptr; - AbstractMetaFunctionList list = metaClass->queryFunctionsByName(QLatin1String("qt_metacall")); + AbstractMetaFunctionList list = + classContext.metaClass()->queryFunctionsByName(QLatin1String("qt_metacall")); if (list.size() == 1) func = list[0]; @@ -1147,24 +1172,25 @@ void CppGenerator::writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass } } - s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);\n"; + s << INDENT << "int result = " << 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"; // qt_metacast function - writeMetaCast(s, metaClass); + writeMetaCast(s, classContext); } -void CppGenerator::writeMetaCast(QTextStream &s, const AbstractMetaClass *metaClass) +void CppGenerator::writeMetaCast(QTextStream &s, const GeneratorContext &classContext) { Indentation indentation(INDENT); - QString wrapperClassName = wrapperName(metaClass); + const QString wrapperClassName = classContext.wrapperName(); + const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName(); s << "void *" << wrapperClassName << "::qt_metacast(const char *_clname)\n{\n"; s << INDENT << "if (!_clname) return {};\n"; s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n"; s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))\n"; s << INDENT << INDENT << "return static_cast<void *>(const_cast< " << wrapperClassName << " *>(this));\n"; - s << INDENT << "return " << metaClass->qualifiedCppName() << "::qt_metacast(_clname);\n"; + s << INDENT << "return " << qualifiedCppName << "::qt_metacast(_clname);\n"; s << "}\n\n"; } @@ -1215,7 +1241,7 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry * } c << ";\n"; writeCppToPythonFunction(s, code, typeName, typeName); - s << endl; + s << Qt::endl; if (enumType->isFlags()) return; @@ -1257,7 +1283,7 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry * } void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext) + const GeneratorContext &classContext) { s << "// Type conversion functions.\n\n"; @@ -1295,7 +1321,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla const QString pyTypeCheck = QLatin1String("PyObject_TypeCheck(pyIn, reinterpret_cast<PyTypeObject *>(") + cpythonType + QLatin1String("))"); writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true); - s << endl; + s << Qt::endl; // C++ pointer to a Python wrapper, keeping identity. s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity).\n"; @@ -1320,7 +1346,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla << INDENT << "if (sbkType && Shiboken::ObjectType::hasSpecialCastFunction(sbkType)) {\n" << INDENT << " typeName = typeNameOf(tCppIn);\n" << INDENT << " changedTypeName = true;\n" - << INDENT << " }\n" + << INDENT << "}\n" << INDENT << "PyObject *result = Shiboken::Object::newObject(" << cpythonType << ", const_cast<void *>(cppIn), false, /* exactType */ changedTypeName, typeName);\n" << INDENT << "if (changedTypeName)\n" @@ -1332,12 +1358,12 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // The conversions for an Object Type end here. if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) { - s << endl; + s << Qt::endl; return; } // Always copies C++ value (not pointer, and not reference) to a new Python wrapper. - s << endl << "// C++ to Python copy conversion.\n"; + s << Qt::endl << "// C++ to Python copy conversion.\n"; if (!classContext.forSmartPointer()) targetTypeName = metaClass->name(); else @@ -1348,16 +1374,18 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla code.clear(); QString computedWrapperName; - if (!classContext.forSmartPointer()) - computedWrapperName = wrapperName(metaClass); - else - computedWrapperName = wrapperName(classContext.preciseType()); + if (!classContext.forSmartPointer()) { + computedWrapperName = classContext.useWrapper() + ? classContext.wrapperName() : metaClass->qualifiedCppName(); + } else { + computedWrapperName = classContext.smartPointerWrapperName(); + } c << INDENT << "return Shiboken::Object::newObject(" << cpythonType << ", new ::" << computedWrapperName << "(*reinterpret_cast<const " << typeName << " *>(cppIn)), true, true);"; writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); - s << endl; + s << Qt::endl; // Python to C++ copy conversion. s << "// Python to C++ copy conversion.\n"; @@ -1382,7 +1410,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // "Is convertible" function for the Python object to C++ value copy conversion. writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck); - s << endl; + s << Qt::endl; // User provided implicit conversions. CustomConversion *customConversion = metaClass->typeEntry()->customConversion(); @@ -1477,42 +1505,42 @@ void CppGenerator::writeCustomConverterFunctions(QTextStream &s, const CustomCon s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'.\n"; for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType()); - s << endl; + s << Qt::endl; } void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext) + const GeneratorContext &classContext) { if (metaClass->isNamespace()) return; s << INDENT << "// Register Converter\n"; s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter("; - s << cpythonTypeName(metaClass) << ',' << endl; + s << cpythonTypeName(metaClass) << ',' << Qt::endl; { Indentation indent(INDENT); QString sourceTypeName = metaClass->name(); QString targetTypeName = sourceTypeName + QLatin1String("_PTR"); - s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; - s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; + s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl; + s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl; std::swap(targetTypeName, sourceTypeName); s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { - s << ',' << endl; + s << ',' << Qt::endl; sourceTypeName = metaClass->name() + QLatin1String("_COPY"); s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); } } s << ");\n"; - s << endl; + s << Qt::endl; QStringList cppSignature; if (!classContext.forSmartPointer()) { cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"), - QString::SkipEmptyParts); + Qt::SkipEmptyParts); } else { cppSignature = classContext.preciseType()->cppSignature().split(QLatin1String("::"), - QString::SkipEmptyParts); + Qt::SkipEmptyParts); } while (!cppSignature.isEmpty()) { QString signature = cppSignature.join(QLatin1String("::")); @@ -1531,12 +1559,12 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas s << qualifiedCppNameInvocation << ").name());\n"; - if (shouldGenerateCppWrapper(metaClass)) { + if (classContext.useWrapper()) { s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::"; - s << wrapperName(metaClass) << ").name());\n"; + s << classContext.wrapperName() << ").name());\n"; } - s << endl; + s << Qt::endl; if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) return; @@ -1608,10 +1636,11 @@ void CppGenerator::writeContainerConverterFunctions(QTextStream &s, const Abstra } void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, - GeneratorContext &context) + const GeneratorContext &context) { const AbstractMetaFunction *rfunc = overloadData.referenceFunction(); const AbstractMetaClass *ownerClass = rfunc->ownerClass(); + Q_ASSERT(ownerClass == context.metaClass()); int minArgs = overloadData.minArgs(); int maxArgs = overloadData.maxArgs(); bool initPythonArguments; @@ -1631,15 +1660,14 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over s << qualifiedCppName << " >()))\n"; Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; } // Declare pointer for the underlying C++ object. s << INDENT << "::"; if (!context.forSmartPointer()) { - s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass) - : ownerClass->qualifiedCppName()); + s << (context.useWrapper() ? context.wrapperName() : ownerClass->qualifiedCppName()); } else { - s << context.preciseType()->cppSignature(); + s << context.smartPointerWrapperName(); } s << " *cptr{};\n"; @@ -1673,10 +1701,10 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over } if (usesNamedArguments && !rfunc->isCallOperator()) - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);\n"; + s << INDENT << "const Py_ssize_t numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);\n"; if (initPythonArguments) { - s << INDENT << "int numArgs = "; + s << INDENT << "const Py_ssize_t numArgs = "; if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData)) s << "(" << PYTHON_ARG << " == 0 ? 0 : 1);\n"; else @@ -1685,7 +1713,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over } void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads, - GeneratorContext &classContext) + const GeneratorContext &classContext) { ErrorCode errorCode(-1); OverloadData overloadData(overloads, this); @@ -1736,7 +1764,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun s << INDENT << "\"'" << metaClass->qualifiedCppName(); } s << "' represents a C++ abstract class and cannot be instantiated\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT<< "}\n\n"; } @@ -1755,24 +1783,24 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun writeMethodWrapperPreamble(s, overloadData, classContext); - s << endl; + s << Qt::endl; if (overloadData.maxArgs() > 0) writeOverloadedFunctionDecisor(s, overloadData); writeFunctionCalls(s, overloadData, classContext); - s << endl; + s << Qt::endl; s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {\n"; { Indentation indent(INDENT); s << INDENT << "delete cptr;\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; if (overloadData.maxArgs() > 0) { s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;\n"; - s << endl; + s << Qt::endl; } s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);\n"; @@ -1794,13 +1822,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun // Create metaObject and register signal/slot if (metaClass->isQObject() && usePySideExtensions()) { - s << endl << INDENT << "// QObject setup\n"; + s << Qt::endl << INDENT << "// QObject setup\n"; s << INDENT << "PySide::Signal::updateSourceObject(self);\n"; s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties\n"; s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))\n"; { Indentation indentation(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } } @@ -1823,7 +1851,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); for (const CodeSnip &cs : injectedCodeSnips) { if (cs.position == TypeSystem::CodeSnipPositionEnd) { - s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; + s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << Qt::endl; s << INDENT << "{\n"; { Indentation indent(INDENT); @@ -1837,15 +1865,15 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun s << "}\n"; } - s << endl; - s << endl << INDENT << "return 1;\n"; + s << Qt::endl; + s << Qt::endl << INDENT << "return 1;\n"; if (overloadData.maxArgs() > 0) writeErrorSection(s, overloadData); s<< "}\n\n"; } void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads, - GeneratorContext &classContext) + const GeneratorContext &classContext) { OverloadData overloadData(overloads, this); const AbstractMetaFunction *rfunc = overloadData.referenceFunction(); @@ -1863,7 +1891,7 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction writeMethodWrapperPreamble(s, overloadData, classContext); - s << endl; + s << Qt::endl; /* * This code is intended for shift operations only: @@ -1926,9 +1954,9 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction writeFunctionCalls(s, overloadData, classContext); if (callExtendedReverseOperator) - s << endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n"; + s << Qt::endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n"; - s << endl; + s << Qt::endl; writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator()); @@ -1960,9 +1988,9 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << INDENT << "PyObject *"; s << PYTHON_ARGS << "[] = {" - << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), QString::SkipEmptyParts).join(QLatin1String(", ")) + << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), Qt::SkipEmptyParts).join(QLatin1String(", ")) << "};\n"; - s << endl; + s << Qt::endl; if (overloadData.hasVarargs()) { maxArgs--; @@ -1973,7 +2001,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);\n"; s << INDENT << PYTHON_ARGS << '[' << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);\n"; s << INDENT << "Shiboken::AutoDecRef auto_varargs(" << PYTHON_ARGS << "[" << maxArgs << "]);\n"; - s << endl; + s << Qt::endl; } bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); @@ -1986,7 +2014,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << '}'; } @@ -1999,7 +2027,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << '}'; } @@ -2017,7 +2045,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl Indentation indent(INDENT); s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; } - s << endl << endl; + s << Qt::endl << Qt::endl; QString funcName; if (rfunc->isOperatorOverload()) @@ -2036,21 +2064,15 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl s << "))\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } - s << endl; + s << Qt::endl; } -void CppGenerator::writeCppSelfAssigment(QTextStream &s, const GeneratorContext &context, - const QString &className, bool cppSelfAsReference, - bool useWrapperClass) +void CppGenerator::writeCppSelfConversion(QTextStream &s, const GeneratorContext &context, + const QString &className, bool useWrapperClass) { static const QString pythonSelfVar = QLatin1String("self"); - if (cppSelfAsReference) - s << className << " &"; - s << CPP_SELF_VAR << " = "; - if (cppSelfAsReference) - s << " *"; if (useWrapperClass) s << "static_cast<" << className << " *>("; if (!context.forSmartPointer()) @@ -2062,49 +2084,57 @@ void CppGenerator::writeCppSelfAssigment(QTextStream &s, const GeneratorContext } void CppGenerator::writeCppSelfDefinition(QTextStream &s, - GeneratorContext &context, + const GeneratorContext &context, bool hasStaticOverload, bool cppSelfAsReference) { + Q_ASSERT(!(cppSelfAsReference && hasStaticOverload)); + const AbstractMetaClass *metaClass = context.metaClass(); bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers(); + Q_ASSERT(!useWrapperClass || context.useWrapper()); QString className; if (!context.forSmartPointer()) { className = useWrapperClass - ? wrapperName(metaClass) + ? context.wrapperName() : (QLatin1String("::") + metaClass->qualifiedCppName()); } else { - className = context.preciseType()->cppSignature(); + className = context.smartPointerWrapperName(); } - if (!cppSelfAsReference) { - s << INDENT << className << " *" << CPP_SELF_VAR << " = nullptr;\n"; - writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); + writeInvalidPyObjectCheck(s, QLatin1String("self")); + + if (cppSelfAsReference) { + s << INDENT << "auto &" << CPP_SELF_VAR << " = *"; + writeCppSelfConversion(s, context, className, useWrapperClass); + s << ";\n"; + return; } - // Checks if the underlying C++ object is valid. - if (hasStaticOverload && !cppSelfAsReference) { - s << INDENT << "if (self) {\n"; - { - Indentation indent(INDENT); - writeInvalidPyObjectCheck(s, QLatin1String("self")); - s << INDENT; - writeCppSelfAssigment(s, context, className, cppSelfAsReference, useWrapperClass); - s << ";\n"; - } - s << INDENT << "}\n"; + if (!hasStaticOverload) { + s << INDENT << "auto " << CPP_SELF_VAR << " = "; + writeCppSelfConversion(s, context, className, useWrapperClass); + s << ";\n"; + writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); return; } - writeInvalidPyObjectCheck(s, QLatin1String("self")); - s << INDENT; - writeCppSelfAssigment(s, context, className, cppSelfAsReference, useWrapperClass); - s << ";\n"; + s << INDENT << className << " *" << CPP_SELF_VAR << " = nullptr;\n"; + writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); + + // Checks if the underlying C++ object is valid. + s << INDENT << "if (self)\n"; + { + Indentation indent(INDENT); + s << INDENT << CPP_SELF_VAR << " = "; + writeCppSelfConversion(s, context, className, useWrapperClass); + s << ";\n"; + } } void CppGenerator::writeCppSelfDefinition(QTextStream &s, const AbstractMetaFunction *func, - GeneratorContext &context, + const GeneratorContext &context, bool hasStaticOverload) { if (!func->ownerClass() || func->isConstructor()) @@ -2128,7 +2158,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s, void CppGenerator::writeErrorSection(QTextStream &s, OverloadData &overloadData) { const AbstractMetaFunction *rfunc = overloadData.referenceFunction(); - s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:\n"; + s << Qt::endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:\n"; Indentation indentation(INDENT); QString funcName = fullPythonFunctionName(rfunc); @@ -2148,7 +2178,7 @@ void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream &s, bool has Indentation indent(INDENT); if (hasReturnValue) s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } @@ -2157,7 +2187,7 @@ void CppGenerator::writeInvalidPyObjectCheck(QTextStream &s, const QString &pyOb { s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))\n"; Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } static QString pythonToCppConverterForArgumentName(const QString &argumentName) @@ -2423,7 +2453,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s, if (!defaultValue.isEmpty()) s << INDENT << '}'; - s << endl; + s << Qt::endl; } static void addConversionRuleCodeSnippet(CodeSnipList &snippetList, QString &rule, @@ -2486,10 +2516,10 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const Overload s << "static "; if (const auto *decl = func->declaringClass()) s << decl->name() << "::"; - s << func->minimalSignature() << endl; + s << func->minimalSignature() << Qt::endl; } writeOverloadedFunctionDecisorEngine(s, &overloadData); - s << endl; + s << Qt::endl; // Ensure that the direct overload that called this reverse // is called. @@ -2505,7 +2535,7 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const Overload s << INDENT << "// Function signature not found.\n"; s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;\n"; - s << endl; + s << Qt::endl; } void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const OverloadData *parentOverloadData) @@ -2536,7 +2566,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov // Functions without arguments are identified right away. if (maxArgs == 0) { s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction); - s << "; // " << referenceFunction->minimalSignature() << endl; + s << "; // " << referenceFunction->minimalSignature() << Qt::endl; return; } @@ -2552,7 +2582,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov if (isLastArgument || (signatureFound && !hasDefaultCall)) { const AbstractMetaFunction *func = parentOverloadData->referenceFunction(); s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; + s << "; // " << func->minimalSignature() << Qt::endl; return; } } @@ -2578,7 +2608,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov } } s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; + s << "; // " << func->minimalSignature() << Qt::endl; } s << INDENT << '}'; } @@ -2635,9 +2665,11 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov if (usePyArgs && signatureFound) { AbstractMetaArgumentList args = refFunc->arguments(); - int lastArgIsVarargs = (int) (args.size() > 1 && args.constLast()->type()->isVarargs()); - int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; - typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); + const bool isVarargs = args.size() > 1 && args.constLast()->type()->isVarargs(); + int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc); + if (isVarargs) + --numArgs; + typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(isVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); } else if (sequenceArgCount > 1) { typeChecks.prepend(QString::fromLatin1("numArgs >= %1").arg(startArg + sequenceArgCount)); } else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) { @@ -2657,7 +2689,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov Indentation indent(INDENT); QString separator; QTextStream sep(&separator); - sep << endl << INDENT << "&& "; + sep << Qt::endl << INDENT << "&& "; s << typeChecks.join(separator); } s << ") {\n"; @@ -2667,11 +2699,11 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov } s << INDENT << "}"; } - s << endl; + s << Qt::endl; } void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, - GeneratorContext &context) + const GeneratorContext &context) { const OverloadData::MetaFunctionList &overloads = overloadData.overloadsWithoutRepetition(); s << INDENT << "// Call function/method\n"; @@ -2683,7 +2715,7 @@ void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overlo } else { for (int i = 0; i < overloads.count(); i++) { const AbstractMetaFunction *func = overloads.at(i); - s << INDENT << "case " << i << ": // " << func->signature() << endl; + s << INDENT << "case " << i << ": // " << func->signature() << Qt::endl; s << INDENT << "{\n"; { Indentation indent(INDENT); @@ -2706,7 +2738,7 @@ void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overlo void CppGenerator::writeSingleFunctionCall(QTextStream &s, const OverloadData &overloadData, const AbstractMetaFunction *func, - GeneratorContext &context) + const GeneratorContext &context) { if (func->isDeprecated()) { s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '" @@ -2718,7 +2750,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" << func->signature().replace(QLatin1String("::"), QLatin1String(".")) << "\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; return; } @@ -2727,7 +2759,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, // Handle named arguments. writeNamedArgumentResolution(s, func, usePyArgs); - bool injectCodeCallsFunc = injectedCodeCallsCppFunction(func); + bool injectCodeCallsFunc = injectedCodeCallsCppFunction(context, func); bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc; int removedArgs = 0; for (int argIdx = 0; argIdx < func->arguments().count(); ++argIdx) { @@ -2761,7 +2793,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded()); } - s << endl; + s << Qt::endl; int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); @@ -2825,8 +2857,9 @@ void CppGenerator::writeCppToPythonFunction(QTextStream &s, const QString &code, static void replaceCppToPythonVariables(QString &code, const QString &typeName) { - code.prepend(QLatin1String("auto &cppInRef = *reinterpret_cast<") - + typeName + QLatin1String(" *>(const_cast<void *>(cppIn));\n")); + const QString line = QLatin1String("auto &cppInRef = *reinterpret_cast<") + + typeName + QLatin1String(" *>(const_cast<void *>(cppIn));"); + CodeSnipAbstract::prependCode(&code, line); code.replace(QLatin1String("%INTYPE"), typeName); code.replace(QLatin1String("%OUTTYPE"), QLatin1String("PyObject *")); code.replace(QLatin1String("%in"), QLatin1String("cppInRef")); @@ -2916,7 +2949,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, if (conversion.isEmpty()) conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); if (!preConversion.isEmpty()) - c << INDENT << preConversion << endl; + c << INDENT << preConversion << Qt::endl; const QString fullTypeName = getFullTypeName(targetType->typeEntry()); c << INDENT << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = " << fullTypeName << '(' << conversion << ");"; @@ -2928,7 +2961,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, if (typeCheck.isEmpty()) typeCheck = QString::fromLatin1("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType); writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); - s << endl; + s << Qt::endl; } void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, @@ -3000,11 +3033,10 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, const Abs } // Python to C++ conversion function. QString cppTypeName = getFullTypeNameWithoutModifiers(containerType); - QString code; - QTextStream c(&code); - c << INDENT << "auto &cppOutRef = *reinterpret_cast<" - << cppTypeName << " *>(cppOut);\n"; - code.append(toCppConversions.constFirst()->conversion()); + QString code = toCppConversions.constFirst()->conversion(); + const QString line = QLatin1String("auto &cppOutRef = *reinterpret_cast<") + + cppTypeName + QLatin1String(" *>(cppOut);"); + CodeSnipAbstract::prependCode(&code, line); for (int i = 0; i < containerType->instantiations().count(); ++i) { const AbstractMetaType *type = containerType->instantiations().at(i); QString typeName = getFullTypeName(type); @@ -3036,15 +3068,15 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, const Abs else typeCheck = QString::fromLatin1("%1pyIn)").arg(typeCheck); writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck); - s << endl; + s << Qt::endl; } void CppGenerator::writeAddPythonToCppConversion(QTextStream &s, const QString &converterVar, const QString &pythonToCppFunc, const QString &isConvertibleFunc) { - s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl; + s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << Qt::endl; { Indentation indent(INDENT); - s << INDENT << pythonToCppFunc << ',' << endl; + s << INDENT << pythonToCppFunc << ',' << Qt::endl; s << INDENT << isConvertibleFunc; } s << ");\n"; @@ -3075,8 +3107,8 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream &s, const AbstractMe s << INDENT << "if (value && " << pyArgName << ") {\n"; { Indentation indent(INDENT); - s << INDENT << pyErrString.arg(arg->name()) << endl; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << pyErrString.arg(arg->name()) << Qt::endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; s << INDENT << "if (value) {\n"; @@ -3149,9 +3181,9 @@ static QStringList defaultExceptionHandling() } void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, - GeneratorContext &context, int maxArgs) + const GeneratorContext &context, int maxArgs) { - s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; + s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << Qt::endl; if (func->isConstructor()) { const CodeSnipList &snips = func->injectedCodeSnips(); for (const CodeSnip &cs : snips) { @@ -3171,7 +3203,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } @@ -3198,7 +3230,6 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg); - s << endl; } writeConversionRule(s, func, TypeSystem::NativeCode); @@ -3283,14 +3314,14 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f std::swap(firstArg, secondArg); QString op = func->originalName(); - op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1)); + op.remove(0, int(std::strlen("operator"))); if (func->isBinaryOperator()) { if (func->isReverseOperator()) std::swap(firstArg, secondArg); if (((op == QLatin1String("++")) || (op == QLatin1String("--"))) && !func->isReverseOperator()) { - s << endl << INDENT << "for (int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");\n"; + s << Qt::endl << INDENT << "for (int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");\n"; mc << firstArg; } else { mc << firstArg << ' ' << op << ' ' << secondArg; @@ -3298,16 +3329,19 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } else { mc << op << ' ' << secondArg; } - } else if (!injectedCodeCallsCppFunction(func)) { + } else if (!injectedCodeCallsCppFunction(context, func)) { if (func->isConstructor()) { isCtor = true; - QString className = wrapperName(func->ownerClass()); + const auto owner = func->ownerClass(); + Q_ASSERT(owner == context.metaClass()); + QString className = context.useWrapper() + ? context.wrapperName() : owner->qualifiedCppName(); if (func->functionType() == AbstractMetaFunction::CopyConstructorFunction && maxArgs == 1) { mc << "new ::" << className << "(*" << CPP_ARG0 << ')'; } else { QString ctorCall = className + QLatin1Char('(') + userArgs.join(QLatin1String(", ")) + QLatin1Char(')'); - if (usePySideExtensions() && func->ownerClass()->isQObject()) { + if (usePySideExtensions() && owner->isQObject()) { s << INDENT << "void *addr = PySide::nextQObjectMemoryAddr();\n"; uva << "if (addr) {\n"; { @@ -3317,7 +3351,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f << ctorCall << ";\n" << INDENT << "PySide::setNextQObjectMemoryAddr(0);" - << endl; + << Qt::endl; } uva << INDENT << "} else {\n"; { @@ -3410,7 +3444,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } } - if (!injectedCodeCallsCppFunction(func)) { + if (!injectedCodeCallsCppFunction(context, func)) { const bool allowThread = func->allowThread(); const bool generateExceptionHandling = func->generateExceptionHandling(); if (generateExceptionHandling) { @@ -3421,12 +3455,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f << INDENT << "threadSaver.save();\n"; } } else if (allowThread) { - s << INDENT << BEGIN_ALLOW_THREADS << endl; + s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl; } s << INDENT; if (isCtor) { s << (useVAddr.isEmpty() ? - QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl; + QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << Qt::endl; } else if (func->type() && !func->isInplaceOperator()) { bool writeReturnType = true; if (avoidProtectedHack()) { @@ -3486,10 +3520,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } } - if (func->hasInjectedCode() && !func->isConstructor()) { - s << endl; + if (func->hasInjectedCode() && !func->isConstructor()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func, lastArg); - } bool hasReturnPolicy = false; @@ -3512,12 +3544,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f hasReturnPolicy = true; if (!ownership_mods.isEmpty()) { - s << endl << INDENT << "// Ownership transferences.\n"; + s << Qt::endl << INDENT << "// Ownership transferences.\n"; for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) { const AbstractMetaClass *wrappedClass = nullptr; QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (!wrappedClass) { - s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ")\n" << endl; + s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ")\n" << Qt::endl; break; } @@ -3540,7 +3572,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } else { s << "invalidate(" << pyArgName << ");"; } - s << endl; + s << Qt::endl; } } else if (!refcount_mods.isEmpty()) { @@ -3560,7 +3592,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } else { pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (pyArgName.isEmpty()) { - s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl; + s << "#error Invalid reference count modification for argument " << arg_mod.index << Qt::endl << Qt::endl; break; } } @@ -3631,9 +3663,9 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream &s, c for (const QString &ancestor : ancestors) s << INDENT << "offsets.insert(int(" << ancestor << "));\n"; - s << endl; + s << Qt::endl; s << INDENT << "offsets.erase(0);\n"; - s << endl; + s << Qt::endl; s << INDENT << "std::copy(offsets.cbegin(), offsets.cend(), mi_offsets);\n"; } @@ -3701,7 +3733,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn { Indentation indent(INDENT); QString typeName = fixedCppTypeName(enumType); - s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl; + s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << Qt::endl; { Indentation indent(INDENT); s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");\n"; @@ -3786,7 +3818,7 @@ void CppGenerator::writeContainerConverterInitialization(QTextStream &s, const A void CppGenerator::writeExtendedConverterInitialization(QTextStream &s, const TypeEntry *externalType, const QVector<const AbstractMetaClass *>& conversions) { - s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl; for (const AbstractMetaClass *sourceClass : conversions) { const QString converterVar = QLatin1String("reinterpret_cast<SbkObjectType *>(") + cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[') @@ -3868,7 +3900,7 @@ QTextStream &operator<<(QTextStream &str, const pyTypeSlotEntry &e) void CppGenerator::writeClassDefinition(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext) + const GeneratorContext &classContext) { QString tp_flags; QString tp_init; @@ -3901,11 +3933,8 @@ void CppGenerator::writeClassDefinition(QTextStream &s, QLatin1String("Sbk_object_dealloc /* PYSIDE-832: Prevent replacement of \"0\" with subtype_dealloc. */"); tp_init.clear(); } else { - QString deallocClassName; - if (shouldGenerateCppWrapper(metaClass)) - deallocClassName = wrapperName(metaClass); - else - deallocClassName = cppClassName; + QString deallocClassName = classContext.useWrapper() + ? classContext.wrapperName() : cppClassName; if (isQApp) tp_dealloc = QLatin1String("&SbkDeallocQAppWrapper"); else @@ -3974,7 +4003,7 @@ void CppGenerator::writeClassDefinition(QTextStream &s, if (metaClass == miClass) writeMultipleInheritanceInitializerFunction(s, metaClass); writeSpecialCastFunction(s, metaClass); - s << endl; + s << Qt::endl; } s << "// Class Definition -----------------------------------------------\n"; @@ -4003,7 +4032,7 @@ void CppGenerator::writeClassDefinition(QTextStream &s, s << "{\n"; s << INDENT << "return " << typePtr << ";\n"; s << "}\n"; - s << endl; + s << Qt::endl; s << "static PyType_Slot " << className << "_slots[] = {\n"; s << INDENT << "{Py_tp_base, nullptr}, // inserted by introduceWrapperType\n"; s << INDENT << pyTypeSlotEntry("Py_tp_dealloc", tp_dealloc) @@ -4046,13 +4075,13 @@ void CppGenerator::writeClassDefinition(QTextStream &s, s << INDENT << tp_flags << ",\n"; s << INDENT << className << "_slots\n"; s << "};\n"; - s << endl; - s << "} //extern \"C\"" << endl; + s << Qt::endl; + s << "} //extern \"C\"" << Qt::endl; } void CppGenerator::writeMappingMethods(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &context) + const GeneratorContext &context) { for (auto it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { const AbstractMetaFunction *func = metaClass->findFunction(it.key()); @@ -4076,7 +4105,7 @@ void CppGenerator::writeMappingMethods(QTextStream &s, void CppGenerator::writeSequenceMethods(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &context) + const GeneratorContext &context) { bool injectedCode = false; @@ -4095,13 +4124,13 @@ void CppGenerator::writeSequenceMethods(QTextStream &s, writeCppSelfDefinition(s, func, context); - const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); + const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast(); writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); s<< "}\n\n"; } if (!injectedCode) - writeStdListWrapperMethods(s, context); + writeDefaultSequenceMethods(s, context); } void CppGenerator::writeTypeAsSequenceDefinition(QTextStream &s, const AbstractMetaClass *metaClass) @@ -4262,7 +4291,7 @@ void CppGenerator::writeTpClearFunction(QTextStream &s, const AbstractMetaClass s << "}\n"; } -void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeCopyFunction(QTextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); const QString className = chopType(cpythonTypeName(metaClass)); @@ -4280,12 +4309,12 @@ void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) writeFunctionReturnErrorCheckSection(s); s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n"; s << "}\n"; - s << endl; + s << Qt::endl; } void CppGenerator::writeGetterFunction(QTextStream &s, const AbstractMetaField *metaField, - GeneratorContext &context) + const GeneratorContext &context) { ErrorCode errorCode(QString::fromLatin1(NULL_PTR)); s << "static PyObject *" << cpythonGetterFunctionName(metaField) << "(PyObject *self, void *)\n"; @@ -4300,7 +4329,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s, QString cppField; if (avoidProtectedHack() && metaField->isProtected()) { QTextStream(&cppField) << "static_cast<" - << wrapperName(metaField->enclosingClass()) << " *>(" + << context.wrapperName() << " *>(" << CPP_SELF_VAR << ")->" << protectedFieldGetterName(metaField) << "()"; } else { cppField = QLatin1String(CPP_SELF_VAR) + QLatin1String("->") + metaField->name(); @@ -4367,7 +4396,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s, void CppGenerator::writeSetterFunction(QTextStream &s, const AbstractMetaField *metaField, - GeneratorContext &context) + const GeneratorContext &context) { ErrorCode errorCode(0); s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject *self, PyObject *pyIn, void *)\n"; @@ -4404,7 +4433,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s, s << getFullTypeNameWithoutModifiers(fieldType); s << (fieldType->indirections() == 1 ? " *" : "") << " cppOut;\n"; s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);\n"; - s << INDENT << "static_cast<" << wrapperName(metaField->enclosingClass()) + s << INDENT << "static_cast<" << context.wrapperName() << " *>(" << CPP_SELF_VAR << ")->" << protectedFieldSetterName(metaField) << "(cppOut)"; } else if (isCppIntegralPrimitive(fieldType) || fieldType->typeEntry()->isEnum() || fieldType->typeEntry()->isFlags()) { @@ -4419,7 +4448,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s, s << cppField << ";\n"; s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)"; } - s << ";\n" << endl; + s << ";\n" << Qt::endl; if (isPointerToWrapperType(fieldType)) { s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(self), \""; @@ -4430,7 +4459,7 @@ void CppGenerator::writeSetterFunction(QTextStream &s, s << "}\n"; } -void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeRichCompareFunction(QTextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); QString baseName = cpythonBaseName(metaClass); @@ -4442,7 +4471,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};\n"; s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n"; writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); - s << endl; + s << Qt::endl; s << INDENT << "switch (op) {\n"; { @@ -4452,7 +4481,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co const AbstractMetaFunction *rfunc = overloads[0]; QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc); - s << INDENT << "case " << operatorId << ':' << endl; + s << INDENT << "case " << operatorId << ':' << Qt::endl; Indentation indent(INDENT); @@ -4487,7 +4516,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co s << ") {\n"; { Indentation indent(INDENT); - s << INDENT << "// " << func->signature() << endl; + s << INDENT << "// " << func->signature() << Qt::endl; writeArgumentConversion(s, argType, QLatin1String(CPP_ARG0), QLatin1String(PYTHON_ARG), metaClass, QString(), func->isUserAdded()); @@ -4547,7 +4576,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co } s << INDENT << baseName << "_RichComparison_TypeError:\n"; s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; s<< "}\n\n"; } @@ -4591,7 +4620,7 @@ void CppGenerator::writeMethodDefinition(QTextStream &s, const AbstractMetaFunct writeMethodDefinitionEntry(s, overloads); s << '}'; } - s << ',' << endl; + s << ',' << Qt::endl; } void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunctionList &overloads) @@ -4612,8 +4641,6 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction strArg += QLatin1Char('='); QString e = arg->defaultValueExpression(); e.replace(QLatin1String("::"), QLatin1String(".")); - // the tests insert stuff like Str("<unknown>"): - e.replace(QLatin1Char('"'), QLatin1String("\\\"")); strArg += e; } args << arg->name() + QLatin1Char(':') + strArg; @@ -4624,7 +4651,7 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction s << funcName << '(' << args.join(QLatin1Char(',')) << ')'; if (f->type()) s << "->" << f->type()->pythonSignature(); - s << endl; + s << Qt::endl; } } @@ -4651,9 +4678,8 @@ static QString mangleName(QString name) void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *cppEnum) { - const AbstractMetaClass *enclosingClass = getProperEnclosingClassForEnum(cppEnum); - const AbstractMetaClass *upper = enclosingClass ? enclosingClass->enclosingClass() : nullptr; - bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + const AbstractMetaClass *enclosingClass = cppEnum->targetLangEnclosingClass(); + bool hasUpperEnclosingClass = enclosingClass && enclosingClass->targetLangEnclosingClass() != nullptr; const EnumTypeEntry *enumTypeEntry = cppEnum->typeEntry(); QString enclosingObjectVariable; if (enclosingClass) @@ -4685,7 +4711,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << enumVarTypeObj << " = Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); - s << '(' << enclosingObjectVariable << ',' << endl; + s << '(' << enclosingObjectVariable << ',' << Qt::endl; { Indentation indent(INDENT); s << INDENT << '"' << cppEnum->name() << "\",\n"; @@ -4693,13 +4719,13 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString()); s << cppEnum->name() << '"'; if (flags) - s << ',' << endl << INDENT << cpythonTypeNameExt(flags); + s << ',' << Qt::endl << INDENT << cpythonTypeNameExt(flags); s << ");\n"; } s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ")\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl; } } @@ -4732,7 +4758,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "Py_DECREF(anonEnumItem);\n"; } @@ -4742,27 +4768,27 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << enumValueText << ") < 0)\n"; { Indentation indent(INDENT); - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } } break; case CEnum: { s << INDENT << "if (!Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); - s << '(' << enumVarTypeObj << ',' << endl; + s << '(' << enumVarTypeObj << ',' << Qt::endl; Indentation indent(INDENT); s << INDENT << enclosingObjectVariable << ", \"" << mangleName(enumValue->name()) << "\", "; s << enumValueText << "))\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } break; case EnumClass: { s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem(" - << enumVarTypeObj << ',' << endl; + << enumVarTypeObj << ',' << Qt::endl; Indentation indent(INDENT); s << INDENT << enumVarTypeObj<< ", \"" << mangleName(enumValue->name()) << "\", " << enumValueText << "))\n" - << INDENT << returnStatement(m_currentErrorCode) << endl; + << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } break; } @@ -4773,7 +4799,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << "// End of '" << cppEnum->name() << "' enum"; if (cppEnum->typeEntry()->flags()) s << "/flags"; - s << '.' << endl << endl; + s << '.' << Qt::endl << Qt::endl; } void CppGenerator::writeSignalInitialization(QTextStream &s, const AbstractMetaClass *metaClass) @@ -4841,7 +4867,7 @@ void CppGenerator::writeFlagsMethods(QTextStream &s, const AbstractMetaEnum *cpp writeFlagsToLong(s, cppEnum); writeFlagsNonZero(s, cppEnum); - s << endl; + s << Qt::endl; } void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const AbstractMetaEnum *cppEnum) @@ -4865,7 +4891,7 @@ void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const Abstr s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long},\n"; s << "#endif\n"; s << INDENT << "{0, " << NULL_PTR << "} // sentinel\n"; - s << "};" << endl << endl; + s << "};\n\n"; } void CppGenerator::writeFlagsBinaryOperator(QTextStream &s, const AbstractMetaEnum *cppEnum, @@ -4936,35 +4962,47 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me return initFunctionName; } -QString CppGenerator::getInitFunctionName(GeneratorContext &context) const +QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const { return !context.forSmartPointer() ? getSimpleClassInitFunctionName(context.metaClass()) : getFilteredCppSignatureString(context.preciseType()->cppSignature()); } +void CppGenerator::writeSignatureStrings(QTextStream &s, + QTextStream &signatureStream, + const QString &arrayName, + const char *comment) const +{ + s << "// The signatures string for the " << comment << ".\n"; + s << "// Multiple signatures have their index \"n:\" in front.\n"; + s << "static const char *" << arrayName << "_SignatureStrings[] = {\n"; + QString line; + while (signatureStream.readLineInto(&line)) { + // must anything be escaped? + if (line.contains(QLatin1Char('"')) || line.contains(QLatin1Char('\\'))) + s << INDENT << "R\"CPP(" << line << ")CPP\",\n"; + else + s << INDENT << '"' << line << "\",\n"; + } + s << INDENT << NULL_PTR << "}; // Sentinel\n\n"; +} + void CppGenerator::writeClassRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext, + const GeneratorContext &classContext, QTextStream &signatureStream) { const ComplexTypeEntry *classTypeEntry = metaClass->typeEntry(); - const AbstractMetaClass *enc = metaClass->enclosingClass(); - bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; - QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module"); + const AbstractMetaClass *enc = metaClass->targetLangEnclosingClass(); + QString enclosingObjectVariable = enc ? QLatin1String("enclosingClass") : QLatin1String("module"); QString pyTypeName = cpythonTypeName(metaClass); QString initFunctionName = getInitFunctionName(classContext); // PYSIDE-510: Create a signatures string for the introspection feature. - s << "// The signatures string for the functions.\n"; - s << "// Multiple signatures have their index \"n:\" in front.\n"; - s << "static const char *" << initFunctionName << "_SignatureStrings[] = {\n"; - QString line; - while (signatureStream.readLineInto(&line)) - s << INDENT << '"' << line << "\",\n"; - s << INDENT << NULL_PTR << "}; // Sentinel\n\n"; + writeSignatureStrings(s, signatureStream, initFunctionName, "functions"); s << "void init_" << initFunctionName; s << "(PyObject *" << enclosingObjectVariable << ")\n{\n"; @@ -4973,7 +5011,7 @@ void CppGenerator::writeClassRegister(QTextStream &s, const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); if (metaClass->baseClassNames().size() > 1) { s << INDENT << "PyObject *" << pyTypeBasesVariable - << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl; + << " = PyTuple_Pack(" << baseClasses.size() << ',' << Qt::endl; Indentation indent(INDENT); for (int i = 0, size = baseClasses.size(); i < size; ++i) { if (i) @@ -5023,10 +5061,12 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << INDENT; if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { QString dtorClassName = metaClass->qualifiedCppName(); - if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue()) - dtorClassName = wrapperName(metaClass); + if (((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue()) + && classContext.useWrapper()) { + dtorClassName = classContext.wrapperName(); + } if (classContext.forSmartPointer()) - dtorClassName = wrapperName(classContext.preciseType()); + dtorClassName = classContext.smartPointerWrapperName(); s << "&Shiboken::callCppDestructor< ::" << dtorClassName << " >,\n"; } else { @@ -5045,13 +5085,13 @@ void CppGenerator::writeClassRegister(QTextStream &s, // 8:baseTypes if (metaClass->baseClassNames().size() > 1) - s << INDENT << pyTypeBasesVariable << ',' << endl; + s << INDENT << pyTypeBasesVariable << ',' << Qt::endl; else s << INDENT << "0,\n"; // 9:wrapperflags QByteArrayList wrapperFlags; - if (hasEnclosingClass) + if (enc) wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass")); if (metaClass->deleteInMainThread()) wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread")); @@ -5061,23 +5101,25 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << INDENT << wrapperFlags.join(" | "); } s << INDENT << ");\n"; - s << INDENT << endl; + s << INDENT << Qt::endl; if (!classContext.forSmartPointer()) - s << INDENT << cpythonTypeNameExt(classTypeEntry) << endl; + s << INDENT << cpythonTypeNameExt(classTypeEntry) << Qt::endl; else - s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << endl; + s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << Qt::endl; s << INDENT << " = reinterpret_cast<PyTypeObject *>(" << pyTypeName << ");\n"; - s << endl; + s << Qt::endl; // Register conversions for the type. writeConverterRegister(s, metaClass, classContext); - s << endl; + s << Qt::endl; // class inject-code target/beginning if (!classTypeEntry->codeSnips().isEmpty()) { - writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, metaClass); - s << endl; + writeClassCodeSnips(s, classTypeEntry->codeSnips(), + TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, + classContext); + s << Qt::endl; } // Fill multiple inheritance data, if needed. @@ -5123,17 +5165,19 @@ void CppGenerator::writeClassRegister(QTextStream &s, writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name()); s << ");\n"; } - s << endl; + s << Qt::endl; // class inject-code target/end if (!classTypeEntry->codeSnips().isEmpty()) { - s << endl; - writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, metaClass); + s << Qt::endl; + writeClassCodeSnips(s, classTypeEntry->codeSnips(), + TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, + classContext); } if (usePySideExtensions()) { - if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass)) - s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n"; + if (avoidProtectedHack() && classContext.useWrapper()) + s << INDENT << classContext.wrapperName() << "::pysideInitQtMetaTypes();\n"; else writeInitQtMetaTypeFunctionBody(s, classContext); } @@ -5152,7 +5196,7 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << "}\n"; } -void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const +void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); // Gets all class name variants used on different possible scopes @@ -5264,10 +5308,14 @@ QString CppGenerator::writeSmartPointerGetterCast() + QLatin1String(SMART_POINTER_GETTER) + QLatin1Char(')'); } -void CppGenerator::writeSetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass) +void CppGenerator::writeSetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass) const { s << "static int " << ShibokenGenerator::cpythonSetattroFunctionName(metaClass) << "(PyObject *self, PyObject *name, PyObject *value)\n{\n"; + if (wrapperDiagnostics()) { + s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << Shiboken::debugPyObject(name) + << ' ' << Shiboken::debugPyObject(value) << '\n';)" << '\n'; + } } inline void CppGenerator::writeSetattroDefaultReturn(QTextStream &s) const @@ -5276,17 +5324,17 @@ inline void CppGenerator::writeSetattroDefaultReturn(QTextStream &s) const } void CppGenerator::writeSetattroFunction(QTextStream &s, AttroCheck attroCheck, - GeneratorContext &context) + const GeneratorContext &context) { Q_ASSERT(!context.forSmartPointer()); const AbstractMetaClass *metaClass = context.metaClass(); writeSetattroDefinition(s, metaClass); // PYSIDE-803: Detect duck-punching; clear cache if a method is set. if (attroCheck.testFlag(AttroCheckFlag::SetattroMethodOverride) - && ShibokenGenerator::shouldGenerateCppWrapper(metaClass)) { + && context.useWrapper()) { s << INDENT << "if (value && PyCallable_Check(value)) {\n"; s << INDENT << " auto plain_inst = " << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n"; - s << INDENT << " auto inst = dynamic_cast<" << wrapperName(metaClass) << " *>(plain_inst);\n"; + s << INDENT << " auto inst = dynamic_cast<" << context.wrapperName() << " *>(plain_inst);\n"; s << INDENT << " if (inst)\n"; s << INDENT << " inst->resetPyMethodCache();\n"; s << INDENT << "}\n"; @@ -5297,10 +5345,26 @@ void CppGenerator::writeSetattroFunction(QTextStream &s, AttroCheck attroCheck, Indentation indent(INDENT); s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);\n"; } + + if (attroCheck.testFlag(AttroCheckFlag::SetattroUser)) { + auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(), + AbstractMetaClass::SetAttroFunction); + Q_ASSERT(func); + s << INDENT << "{\n"; + { + Indentation indent(INDENT); + s << INDENT << "auto " << CPP_SELF_VAR << " = " + << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n"; + writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny, + TypeSystem::TargetLangCode, context); + } + s << INDENT << "}\n"; + } + writeSetattroDefaultReturn(s); } -void CppGenerator::writeSmartPointerSetattroFunction(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeSmartPointerSetattroFunction(QTextStream &s, const GeneratorContext &context) { Q_ASSERT(context.forSmartPointer()); writeSetattroDefinition(s, context.metaClass()); @@ -5346,7 +5410,7 @@ QString CppGenerator::qObjectGetAttroFunction() const } void CppGenerator::writeGetattroFunction(QTextStream &s, AttroCheck attroCheck, - GeneratorContext &context) + const GeneratorContext &context) { Q_ASSERT(!context.forSmartPointer()); const AbstractMetaClass *metaClass = context.metaClass(); @@ -5401,10 +5465,25 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, AttroCheck attroCheck, } } + if (attroCheck.testFlag(AttroCheckFlag::GetattroUser)) { + auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(), + AbstractMetaClass::GetAttroFunction); + Q_ASSERT(func); + s << INDENT << "{\n"; + { + Indentation indent(INDENT); + s << INDENT << "auto " << CPP_SELF_VAR << " = " + << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n"; + writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny, + TypeSystem::TargetLangCode, context); + } + s << INDENT << "}\n"; + } + s << INDENT << "return " << getattrFunc << ";\n}\n\n"; } -void CppGenerator::writeSmartPointerGetattroFunction(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeSmartPointerGetattroFunction(QTextStream &s, const GeneratorContext &context) { Q_ASSERT(context.forSmartPointer()); const AbstractMetaClass *metaClass = context.metaClass(); @@ -5450,6 +5529,25 @@ void CppGenerator::writeSmartPointerGetattroFunction(QTextStream &s, GeneratorCo s << INDENT << "return tmp;\n}\n\n"; } +// Write declaration and invocation of the init function for the module init +// function. +void CppGenerator::writeInitFunc(QTextStream &declStr, QTextStream &callStr, + const Indentor &indent, const QString &initFunctionName, + const TypeEntry *enclosingEntry) +{ + const bool hasParent = + enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType; + declStr << "void init_" << initFunctionName << "(PyObject *" + << (hasParent ? "enclosingClass" : "module") << ");\n"; + callStr << indent << "init_" << initFunctionName; + if (hasParent) { + callStr << "(reinterpret_cast<PyTypeObject *>(" + << cpythonTypeNameExt(enclosingEntry) << ")->tp_dict);\n"; + } else { + callStr << "(module);\n"; + } +} + bool CppGenerator::finishGeneration() { //Generate CPython wrapper file @@ -5504,33 +5602,20 @@ bool CppGenerator::finishGeneration() const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); for (const AbstractMetaClass *cls : lst){ - if (!shouldGenerate(cls)) - continue; - - const QString initFunctionName = QLatin1String("init_") + getSimpleClassInitFunctionName(cls); - - s_classInitDecl << "void " << initFunctionName << "(PyObject *module);" << endl; - - s_classPythonDefines << INDENT << initFunctionName; - if (cls->enclosingClass() - && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) { - s_classPythonDefines << "(reinterpret_cast<PyTypeObject *>(" - << cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) << ")->tp_dict);"; - } else { - s_classPythonDefines << "(module);"; + if (shouldGenerate(cls)) { + writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT, + getSimpleClassInitFunctionName(cls), + cls->typeEntry()->targetLangEnclosingEntry()); } - s_classPythonDefines << endl; } // Initialize smart pointer types. const QVector<const AbstractMetaType *> &smartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : smartPtrs) { - GeneratorContext context(nullptr, metaType, true); - QString initFunctionName = getInitFunctionName(context); - s_classInitDecl << "void init_" << initFunctionName << "(PyObject *module);" << endl; - QString defineStr = QLatin1String("init_") + initFunctionName; - defineStr += QLatin1String("(module);"); - s_classPythonDefines << INDENT << defineStr << endl; + GeneratorContext context = contextForSmartPointer(nullptr, metaType); + writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT, + getInitFunctionName(context), + metaType->typeEntry()->targetLangEnclosingEntry()); } QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName())); @@ -5543,7 +5628,7 @@ bool CppGenerator::finishGeneration() QTextStream &s = file.stream; // write license comment - s << licenseComment() << endl; + s << licenseComment() << Qt::endl; s << "#include <sbkpython.h>\n"; s << "#include <shiboken.h>\n"; @@ -5552,22 +5637,22 @@ bool CppGenerator::finishGeneration() if (usePySideExtensions()) { s << includeQDebug; s << "#include <pyside.h>\n"; + s << "#include <pysideqenum.h>\n"; s << "#include <qapp_macro.h>\n"; } - s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; + s << "#include \"" << getModuleHeaderFileName() << '"' << Qt::endl << Qt::endl; for (const Include &include : qAsConst(includes)) s << include; - s << endl; + s << Qt::endl; // Global enums AbstractMetaEnumList globalEnums = this->globalEnums(); const AbstractMetaClassList &classList = classes(); for (const AbstractMetaClass *metaClass : classList) { const AbstractMetaClass *encClass = metaClass->enclosingClass(); - if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - continue; - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + if (!encClass || !NamespaceTypeEntry::isVisibleScope(encClass->typeEntry())) + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); } TypeDatabase *typeDb = TypeDatabase::instance(); @@ -5575,14 +5660,14 @@ bool CppGenerator::finishGeneration() Q_ASSERT(moduleEntry); //Extra includes - s << endl << "// Extra includes\n"; + s << Qt::endl << "// Extra includes\n"; QVector<Include> extraIncludes = moduleEntry->extraIncludes(); for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) extraIncludes.append(cppEnum->typeEntry()->extraIncludes()); std::sort(extraIncludes.begin(), extraIncludes.end()); for (const Include &inc : qAsConst(extraIncludes)) s << inc; - s << endl; + s << Qt::endl; s << "// Current module's type array.\n"; s << "PyTypeObject **" << cppApiVariableName() << " = nullptr;\n"; @@ -5596,10 +5681,8 @@ bool CppGenerator::finishGeneration() const CodeSnipList snips = moduleEntry->codeSnips(); // module inject-code native/beginning - if (!snips.isEmpty()) { + if (!snips.isEmpty()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode); - s << endl; - } // cleanup staticMetaObject attribute if (usePySideExtensions()) { @@ -5623,7 +5706,7 @@ bool CppGenerator::finishGeneration() s << "// Global functions "; s << "------------------------------------------------------------\n"; - s << globalFunctionImpl << endl; + s << globalFunctionImpl << Qt::endl; s << "static PyMethodDef " << moduleName() << "_methods[] = {\n"; s << globalFunctionDecl; @@ -5631,7 +5714,7 @@ bool CppGenerator::finishGeneration() s << "// Classes initialization functions "; s << "------------------------------------------------------------\n"; - s << classInitDecl << endl; + s << classInitDecl << Qt::endl; if (!globalEnums.isEmpty()) { QString converterImpl; @@ -5643,14 +5726,14 @@ bool CppGenerator::finishGeneration() if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; writeEnumConverterFunctions(s, cppEnum); - s << endl; + s << Qt::endl; } if (!converterImpl.isEmpty()) { s << "// Enum converters "; s << "------------------------------------------------------------\n"; s << "namespace Shiboken\n{\n"; - s << converterImpl << endl; + s << converterImpl << Qt::endl; s << "} // namespace Shiboken\n\n"; } } @@ -5662,16 +5745,16 @@ bool CppGenerator::finishGeneration() s << "PyTypeObject **" << cppApiVariableName(requiredModule) << ";\n"; s << "SbkConverter **" << convertersVariableName(requiredModule) << ";\n"; } - s << endl; + s << Qt::endl; s << "// Module initialization "; s << "------------------------------------------------------------\n"; ExtendedConverterData extendedConverters = getExtendedConverters(); if (!extendedConverters.isEmpty()) { - s << endl << "// Extended Converters.\n\n"; + s << Qt::endl << "// Extended Converters.\n\n"; for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { const TypeEntry *externalType = it.key(); - s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl; for (const AbstractMetaClass *sourceClass : it.value()) { AbstractMetaType *sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass); AbstractMetaType *targetType = buildAbstractMetaTypeFromTypeEntry(externalType); @@ -5682,13 +5765,13 @@ bool CppGenerator::finishGeneration() const QVector<const CustomConversion *> &typeConversions = getPrimitiveCustomConversions(); if (!typeConversions.isEmpty()) { - s << endl << "// Primitive Type converters.\n\n"; + s << Qt::endl << "// Primitive Type converters.\n\n"; for (const CustomConversion *conversion : typeConversions) { s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'.\n"; writeCppToPythonFunction(s, conversion); writeCustomConverterFunctions(s, conversion); } - s << endl; + s << Qt::endl; } const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); @@ -5698,7 +5781,7 @@ bool CppGenerator::finishGeneration() s << "// C++ to Python conversion for type '" << container->cppSignature() << "'.\n"; writeContainerConverterFunctions(s, container); } - s << endl; + s << Qt::endl; } s << "#if defined _WIN32 || defined __CYGWIN__\n"; @@ -5724,22 +5807,14 @@ bool CppGenerator::finishGeneration() s << "#endif\n\n"; // PYSIDE-510: Create a signatures string for the introspection feature. - s << "// The signatures string for the global functions.\n"; - s << "// Multiple signatures have their index \"n:\" in front.\n"; - s << "static const char *" << moduleName() << "_SignatureStrings[] = {\n"; - QString line; - while (signatureStream.readLineInto(&line)) - s << INDENT << '"' << line << "\",\n"; - s << INDENT << NULL_PTR << "}; // Sentinel\n\n"; + writeSignatureStrings(s, signatureStream, moduleName(), "global functions"); s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")\n"; ErrorCode errorCode(QLatin1String("SBK_MODULE_INIT_ERROR")); // module inject-code target/beginning - if (!snips.isEmpty()) { + if (!snips.isEmpty()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode); - s << endl; - } for (const QString &requiredModule : requiredModules) { s << INDENT << "{\n"; @@ -5785,26 +5860,26 @@ bool CppGenerator::finishGeneration() s << classPythonDefines; if (!typeConversions.isEmpty()) { - s << endl; + s << Qt::endl; for (const CustomConversion *conversion : typeConversions) { writePrimitiveConverterInitialization(s, conversion); - s << endl; + s << Qt::endl; } } if (!containers.isEmpty()) { - s << endl; + s << Qt::endl; for (const AbstractMetaType *container : containers) { writeContainerConverterInitialization(s, container); - s << endl; + s << Qt::endl; } } if (!extendedConverters.isEmpty()) { - s << endl; + s << Qt::endl; for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { writeExtendedConverterInitialization(s, it.key(), it.value()); - s << endl; + s << Qt::endl; } } @@ -5819,7 +5894,7 @@ bool CppGenerator::finishGeneration() if (!referencedType) continue; QString converter = converterObject(referencedType); - QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts); while (!cppSignature.isEmpty()) { QString signature = cppSignature.join(QLatin1String("::")); s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");\n"; @@ -5827,12 +5902,12 @@ bool CppGenerator::finishGeneration() } } - s << endl; + s << Qt::endl; if (maxTypeIndex) s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n"; s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n"; - s << endl << INDENT << "if (PyErr_Occurred()) {\n"; + s << Qt::endl << INDENT << "if (PyErr_Occurred()) {\n"; { Indentation indentation(INDENT); s << INDENT << "PyErr_Print();\n"; @@ -5841,16 +5916,12 @@ bool CppGenerator::finishGeneration() s << INDENT << "}\n"; // module inject-code target/end - if (!snips.isEmpty()) { + if (!snips.isEmpty()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode); - s << endl; - } // module inject-code native/end - if (!snips.isEmpty()) { + if (!snips.isEmpty()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode); - s << endl; - } if (usePySideExtensions()) { for (AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) @@ -5866,7 +5937,7 @@ bool CppGenerator::finishGeneration() s << INDENT << "FinishSignatureInitialization(module, " << moduleName() << "_SignatureStrings);\n"; - s << endl; + s << Qt::endl; s << "SBK_MODULE_INIT_FUNCTION_END\n"; return file.done() != FileOut::Failure; @@ -5972,17 +6043,20 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream &s, const AbstractMeta } } -void CppGenerator::writeHashFunction(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeHashFunction(QTextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); - s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject *self) {\n"; + const char hashType[] = "Py_hash_t"; + s << "static " << hashType << ' ' << cpythonBaseName(metaClass) + << "_HashFunc(PyObject *self) {\n"; writeCppSelfDefinition(s, context); - s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '('; - s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");\n"; + s << INDENT << "return " << hashType << '(' + << metaClass->typeEntry()->hashFunction() << '(' + << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << "));\n"; s<< "}\n\n"; } -void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context) +void CppGenerator::writeDefaultSequenceMethods(QTextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); ErrorCode errorCode(0); @@ -6000,10 +6074,17 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext & writeCppSelfDefinition(s, context); writeIndexError(s, QLatin1String("index out of bounds")); - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();\n"; - s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;\n"; + QString value; + s << INDENT << metaClass->qualifiedCppName() << "::const_iterator _item = " + << CPP_SELF_VAR << "->begin();\n" + << INDENT << "std::advance(_item, _i);\n"; - const AbstractMetaType *itemType = metaClass->templateBaseClassInstantiations().constFirst(); + const AbstractMetaTypeList instantiations = metaClass->templateBaseClassInstantiations(); + if (instantiations.isEmpty()) { + qFatal("shiboken: %s: Internal error, no instantiations of \"%s\" were found.", + __FUNCTION__, qPrintable(metaClass->qualifiedCppName())); + } + const AbstractMetaType *itemType = instantiations.constFirst(); s << INDENT << "return "; writeToPythonConversion(s, itemType, metaClass, QLatin1String("*_item")); @@ -6030,9 +6111,11 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext & s << INDENT << "}\n"; writeArgumentConversion(s, itemType, QLatin1String("cppValue"), QLatin1String("pyArg"), metaClass); - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();\n"; - s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;\n"; - s << INDENT << "*_item = cppValue;\n"; + s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " + << CPP_SELF_VAR << "->begin();\n" + << INDENT << "std::advance(_item, _i);\n" + << INDENT << "*_item = cppValue;\n"; + s << INDENT << "return {};\n"; s << "}\n"; } @@ -6042,13 +6125,13 @@ void CppGenerator::writeIndexError(QTextStream &s, const QString &errorMsg) { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");\n"; - s << INDENT << returnStatement(m_currentErrorCode) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl; } s << INDENT << "}\n"; } QString CppGenerator::writeReprFunction(QTextStream &s, - GeneratorContext &context, + const GeneratorContext &context, uint indirections) { const AbstractMetaClass *metaClass = context.metaClass(); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index aee1fb7d4..4e995d56f 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -43,53 +43,53 @@ public: protected: QString fileNameSuffix() const override; - QString fileNameForContext(GeneratorContext &context) const override; + QString fileNameForContext(const GeneratorContext &context) const override; QVector<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass *metaClass, uint query); - void generateClass(QTextStream &s, GeneratorContext &classContext) override; + void generateClass(QTextStream &s, const GeneratorContext &classContext) override; bool finishGeneration() override; private: void writeInitFunc(QTextStream &declStr, QTextStream &callStr, const Indentor &indent, const QString &initFunctionName, const TypeEntry *enclosingEntry = nullptr); - void writeCacheResetNative(QTextStream &s, const AbstractMetaClass *metaClass); - void writeConstructorNative(QTextStream &s, const AbstractMetaFunction *func); - void writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass); + void writeCacheResetNative(QTextStream &s, const GeneratorContext &classContext); + void writeConstructorNative(QTextStream &s, const GeneratorContext &classContext, + const AbstractMetaFunction *func); + void writeDestructorNative(QTextStream &s, const GeneratorContext &classContext); QString getVirtualFunctionReturnTypeName(const AbstractMetaFunction *func); void writeVirtualMethodNative(QTextStream &s, const AbstractMetaFunction *func, int cacheIndex); - void writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass *metaClass); - void writeMetaCast(QTextStream &s, const AbstractMetaClass *metaClass); + void writeMetaObjectMethod(QTextStream &s, const GeneratorContext &classContext); + void writeMetaCast(QTextStream &s, const GeneratorContext &classContext); void writeEnumConverterFunctions(QTextStream &s, const TypeEntry *enumType); void writeEnumConverterFunctions(QTextStream &s, const AbstractMetaEnum *metaEnum); void writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext); + const GeneratorContext &classContext); void writeCustomConverterFunctions(QTextStream &s, const CustomConversion *customConversion); void writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext); + const GeneratorContext &classContext); void writeCustomConverterRegister(QTextStream &s, const CustomConversion *customConversion, const QString &converterVar); void writeContainerConverterFunctions(QTextStream &s, const AbstractMetaType *containerType); void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, - GeneratorContext &context); + const GeneratorContext &context); void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads, - GeneratorContext &classContext); + const GeneratorContext &classContext); void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads, - GeneratorContext &classContext); + const GeneratorContext &classContext); void writeArgumentsInitializer(QTextStream &s, OverloadData &overloadData); - void writeCppSelfAssigment(QTextStream &s, const GeneratorContext &context, - const QString &className, bool cppSelfAsReference, - bool useWrapperClass); + void writeCppSelfConversion(QTextStream &s, const GeneratorContext &context, + const QString &className, bool useWrapperClass); void writeCppSelfDefinition(QTextStream &s, const AbstractMetaFunction *func, - GeneratorContext &context, + const GeneratorContext &context, bool hasStaticOverload = false); void writeCppSelfDefinition(QTextStream &s, - GeneratorContext &context, + const GeneratorContext &context, bool hasStaticOverload = false, bool cppSelfAsReference = false); @@ -106,13 +106,15 @@ private: void writeTypeDiscoveryFunction(QTextStream &s, const AbstractMetaClass *metaClass); - static void writeSetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass); + void writeSetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass) const; void writeSetattroDefaultReturn(QTextStream &s) const; - void writeSmartPointerSetattroFunction(QTextStream &s, GeneratorContext &context); - void writeSetattroFunction(QTextStream &s, AttroCheck attroCheck, GeneratorContext &context); + void writeSmartPointerSetattroFunction(QTextStream &s, const GeneratorContext &context); + void writeSetattroFunction(QTextStream &s, AttroCheck attroCheck, + const GeneratorContext &context); static void writeGetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass); - void writeSmartPointerGetattroFunction(QTextStream &s, GeneratorContext &context); - void writeGetattroFunction(QTextStream &s, AttroCheck attroCheck, GeneratorContext &context); + void writeSmartPointerGetattroFunction(QTextStream &s, const GeneratorContext &context); + void writeGetattroFunction(QTextStream &s, AttroCheck attroCheck, + const GeneratorContext &context); QString writeSmartPointerGetterCast(); QString qObjectGetAttroFunction() const; @@ -183,13 +185,13 @@ private: /// Writes calls to all the possible method/function overloads. void writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, - GeneratorContext &context); + const GeneratorContext &context); /// Writes the call to a single function usually from a collection of overloads. void writeSingleFunctionCall(QTextStream &s, const OverloadData &overloadData, const AbstractMetaFunction *func, - GeneratorContext &context); + const GeneratorContext &context); /// Returns the name of a C++ to Python conversion function. static QString cppToPythonFunctionName(const QString &sourceTypeName, QString targetTypeName = QString()); @@ -242,48 +244,51 @@ private: /// 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, - GeneratorContext &context, int maxArgs = 0); + const GeneratorContext &context, int maxArgs = 0); - QString getInitFunctionName(GeneratorContext &context) const; + QString getInitFunctionName(const GeneratorContext &context) const; QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const; + void writeSignatureStrings(QTextStream &s, QTextStream &signatureStream, + const QString &arrayName, + const char *comment) const; void writeClassRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext, + const GeneratorContext &classContext, QTextStream &signatureStream); void writeClassDefinition(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext); + const GeneratorContext &classContext); void writeMethodDefinitionEntry(QTextStream &s, const AbstractMetaFunctionList &overloads); void writeMethodDefinition(QTextStream &s, const AbstractMetaFunctionList &overloads); void writeSignatureInfo(QTextStream &s, const AbstractMetaFunctionList &overloads); /// Writes the implementation of all methods part of python sequence protocol void writeSequenceMethods(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &context); + const GeneratorContext &context); void writeTypeAsSequenceDefinition(QTextStream &s, const AbstractMetaClass *metaClass); /// Writes the PyMappingMethods structure for types that supports the python mapping protocol. void writeTypeAsMappingDefinition(QTextStream &s, const AbstractMetaClass *metaClass); void writeMappingMethods(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &context); + const GeneratorContext &context); void writeTypeAsNumberDefinition(QTextStream &s, const AbstractMetaClass *metaClass); void writeTpTraverseFunction(QTextStream &s, const AbstractMetaClass *metaClass); void writeTpClearFunction(QTextStream &s, const AbstractMetaClass *metaClass); - void writeCopyFunction(QTextStream &s, GeneratorContext &context); + void writeCopyFunction(QTextStream &s, const GeneratorContext &context); void writeGetterFunction(QTextStream &s, const AbstractMetaField *metaField, - GeneratorContext &context); + const GeneratorContext &context); void writeSetterFunction(QTextStream &s, const AbstractMetaField *metaField, - GeneratorContext &context); + const GeneratorContext &context); - void writeRichCompareFunction(QTextStream &s, GeneratorContext &context); + void writeRichCompareFunction(QTextStream &s, const GeneratorContext &context); void writeEnumsInitialization(QTextStream &s, AbstractMetaEnumList &enums); void writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *metaEnum); @@ -314,7 +319,7 @@ private: 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); - void writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const; + void writeInitQtMetaTypeFunctionBody(QTextStream &s, const GeneratorContext &context) const; /** * Returns the multiple inheritance initializer function for the given class. @@ -339,14 +344,14 @@ private: /// Returns true if generator should produce getters and setters for the given class. bool shouldGenerateGetSetList(const AbstractMetaClass *metaClass); - void writeHashFunction(QTextStream &s, GeneratorContext &context); + void writeHashFunction(QTextStream &s, const GeneratorContext &context); /// Write default implementations for sequence protocol - void writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context); + void writeDefaultSequenceMethods(QTextStream &s, const GeneratorContext &context); /// Helper function for writeStdListWrapperMethods. void writeIndexError(QTextStream &s, const QString &errorMsg); - QString writeReprFunction(QTextStream &s, GeneratorContext &context, uint indirections); + QString writeReprFunction(QTextStream &s, const GeneratorContext &context, uint indirections); const AbstractMetaFunction *boolCast(const AbstractMetaClass *metaClass) const; bool hasBoolCast(const AbstractMetaClass *metaClass) const diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index 34bba408a..8b3fe1653 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -45,7 +45,7 @@ QString HeaderGenerator::fileNameSuffix() const return QLatin1String("_wrapper.h"); } -QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const +QString HeaderGenerator::fileNameForContext(const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); if (!context.forSmartPointer()) { @@ -91,11 +91,10 @@ void HeaderGenerator::writeProtectedFieldAccessors(QTextStream &s, const Abstrac << " { " << fieldName << " = value; }\n"; } -void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +void HeaderGenerator::generateClass(QTextStream &s, const GeneratorContext &classContextIn) { - AbstractMetaClass *metaClass = classContext.metaClass(); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "Generating header for " << metaClass->fullName(); + GeneratorContext classContext = classContextIn; + const AbstractMetaClass *metaClass = classContext.metaClass(); m_inheritedOverloads.clear(); Indentation indent(INDENT); @@ -104,9 +103,10 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte QString wrapperName; if (!classContext.forSmartPointer()) { - wrapperName = HeaderGenerator::wrapperName(metaClass); + wrapperName = classContext.useWrapper() + ? classContext.wrapperName() : metaClass->qualifiedCppName(); } else { - wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); + wrapperName = classContext.smartPointerWrapperName(); } QString outerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper(); QString innerHeaderGuard; @@ -119,13 +119,12 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte s << "#define protected public\n\n"; //Includes - s << metaClass->typeEntry()->include() << endl; + s << metaClass->typeEntry()->include() << Qt::endl; - if (shouldGenerateCppWrapper(metaClass) && - usePySideExtensions() && metaClass->isQObject()) + if (classContext.useWrapper() && usePySideExtensions() && metaClass->isQObject()) s << "namespace PySide { class DynamicQMetaObject; }\n\n"; - while (shouldGenerateCppWrapper(metaClass)) { + while (classContext.useWrapper()) { if (!innerHeaderGuard.isEmpty()) { s << "# ifndef SBK_" << innerHeaderGuard << "_H\n"; s << "# define SBK_" << innerHeaderGuard << "_H\n\n"; @@ -171,7 +170,9 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte s << '~' << wrapperName << "();\n"; } - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode); + writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), + TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, + classContext); if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) && usePySideExtensions() && metaClass->isQObject()) { @@ -204,11 +205,12 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte metaClass = metaClass->baseClass(); if (!metaClass || !avoidProtectedHack()) break; - classContext = GeneratorContext(metaClass); + classContext = contextForClass(metaClass); if (!classContext.forSmartPointer()) { - wrapperName = HeaderGenerator::wrapperName(metaClass); + wrapperName = classContext.useWrapper() + ? classContext.wrapperName() : metaClass->qualifiedCppName(); } else { - wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); + wrapperName = classContext.smartPointerWrapperName(); } innerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper(); } @@ -337,7 +339,8 @@ void HeaderGenerator::writeTypeIndexValueLine(QTextStream &s, const TypeEntry *t void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMetaClass *metaClass) { - if (!metaClass->typeEntry()->generateCode()) + auto typeEntry = metaClass->typeEntry(); + if (!typeEntry->generateCode() || !NamespaceTypeEntry::isVisibleScope(typeEntry)) return; writeTypeIndexValueLine(s, metaClass->typeEntry()); const AbstractMetaEnumList &enums = metaClass->enums(); @@ -411,9 +414,17 @@ bool HeaderGenerator::finishGeneration() int smartPointerCount = 0; const QVector<const AbstractMetaType *> &instantiatedSmartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType), - smartPointerCountIndex); - macrosStream << ", // " << metaType->cppSignature() << endl; + QString indexName = getTypeIndexVariableName(metaType); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // " << metaType->cppSignature() << Qt::endl; + // Add a the same value for const pointees (shared_ptr<const Foo>). + const auto ptrName = metaType->typeEntry()->entryName(); + int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive); + if (pos >= 0) { + indexName.insert(pos + ptrName.size() + 1, QLatin1String("CONST")); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // (const)\n"; + } ++smartPointerCountIndex; ++smartPointerCount; } @@ -449,7 +460,7 @@ bool HeaderGenerator::finishGeneration() const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); for (const AbstractMetaType *container : containers) { _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount); - macrosStream << ", // " << container->cppSignature() << endl; + macrosStream << ", // " << container->cppSignature() << Qt::endl; pCount++; } @@ -517,10 +528,10 @@ bool HeaderGenerator::finishGeneration() FileOut file(moduleHeaderFileName); QTextStream &s = file.stream; // write license comment - s << licenseComment() << endl << endl; + s << licenseComment() << Qt::endl << Qt::endl; - s << "#ifndef " << includeShield << endl; - s << "#define " << includeShield << endl << endl; + s << "#ifndef " << includeShield << Qt::endl; + s << "#define " << includeShield << Qt::endl << Qt::endl; if (!avoidProtectedHack()) { s << "//workaround to access protected functions\n"; s << "#define protected public\n\n"; @@ -534,7 +545,7 @@ bool HeaderGenerator::finishGeneration() s << "// Module Includes\n"; for (const QString &requiredModule : qAsConst(requiredTargetImports)) s << "#include <" << getModuleHeaderFileName(requiredModule) << ">\n"; - s << endl; + s << Qt::endl; } s << "// Bound library includes\n"; @@ -546,7 +557,7 @@ bool HeaderGenerator::finishGeneration() const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); for (const PrimitiveTypeEntry *ptype : primitiveTypeList) s << ptype->include(); - s << endl; + s << Qt::endl; } if (!containerTypes().isEmpty()) { @@ -554,24 +565,24 @@ bool HeaderGenerator::finishGeneration() const ContainerTypeEntryList &containerTypeList = containerTypes(); for (const ContainerTypeEntry *ctype : containerTypeList) s << ctype->include(); - s << endl; + s << Qt::endl; } - s << macros << endl; + s << macros << Qt::endl; if (!protectedEnumSurrogates.isEmpty()) { s << "// Protected enum surrogates\n"; - s << protectedEnumSurrogates << endl; + s << protectedEnumSurrogates << Qt::endl; } s << "namespace Shiboken\n{\n\n"; s << "// PyType functions, to get the PyObjectType for a type T\n"; - s << sbkTypeFunctions << endl; + s << sbkTypeFunctions << Qt::endl; s << "} // namespace Shiboken\n\n"; - s << "#endif // " << includeShield << endl << endl; + s << "#endif // " << includeShield << Qt::endl << Qt::endl; return file.done() != FileOut::Failure; } diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.h b/sources/shiboken2/generator/shiboken2/headergenerator.h index 5f59dd13a..30ce06636 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.h +++ b/sources/shiboken2/generator/shiboken2/headergenerator.h @@ -47,8 +47,8 @@ public: protected: QString fileNameSuffix() const override; - QString fileNameForContext(GeneratorContext &context) const override; - void generateClass(QTextStream &s, GeneratorContext &classContext) override; + QString fileNameForContext(const GeneratorContext &context) const override; + void generateClass(QTextStream &s, const GeneratorContext &classContext) override; bool finishGeneration() override; private: diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index 56b64bbd5..bd39e9444 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -106,7 +106,7 @@ struct OverloadSortData return; map[typeName] = counter; if (!reverseMap.contains(counter)) - reverseMap[counter] = 0; + reverseMap[counter] = nullptr; counter++; } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index b6ab70d1f..6abaef698 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -47,6 +47,7 @@ static const char RETURN_VALUE_HEURISTIC[] = "enable-return-value-heuristic"; static const char ENABLE_PYSIDE_EXTENSIONS[] = "enable-pyside-extensions"; static const char DISABLE_VERBOSE_ERROR_MESSAGES[] = "disable-verbose-error-messages"; static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero"; +static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics"; const char *CPP_ARG = "cppArg"; const char *CPP_ARG_REMOVED = "removed_cppArg"; @@ -96,7 +97,7 @@ static QString resolveScopePrefix(const QStringList &scopeList, const QString &v static inline QStringList splitClassScope(const AbstractMetaClass *scope) { - return scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + return scope->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts); } static QString resolveScopePrefix(const AbstractMetaClass *scope, const QString &value) @@ -335,7 +336,7 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi { Q_ASSERT(metaClass); // if a scope is not to be generated, collect its enums into the parent scope - if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { + if (!NamespaceTypeEntry::isVisibleScope(metaClass->typeEntry())) { const AbstractMetaEnumList &enums = metaClass->enums(); for (AbstractMetaEnum *metaEnum : enums) { if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode() @@ -346,47 +347,13 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi } } -static const AbstractMetaClass *getProperEnclosingClass(const AbstractMetaClass *metaClass) -{ - if (!metaClass) - return nullptr; - - if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - return metaClass; - - return getProperEnclosingClass(metaClass->enclosingClass()); -} - -const AbstractMetaClass *ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum *metaEnum) -{ - return getProperEnclosingClass(metaEnum->enclosingClass()); -} - QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const { - if (shouldGenerateCppWrapper(metaClass)) { - QString result = metaClass->name(); - if (metaClass->enclosingClass()) // is a inner class - result.replace(QLatin1String("::"), QLatin1String("_")); - - result += QLatin1String("Wrapper"); - return result; - } - return metaClass->qualifiedCppName(); -} - -QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const -{ - return metaType->cppSignature(); -} - -QString ShibokenGenerator::wrapperName(const TypeEntry *type) const -{ - QString name = type->name(); - int pos = name.lastIndexOf(QLatin1String("::")); - if (pos >= 0) - name = name.remove(0, pos + 2); - return name + QLatin1String("Wrapper"); + Q_ASSERT(shouldGenerateCppWrapper(metaClass)); + QString result = metaClass->name(); + if (metaClass->enclosingClass()) // is a inner class + result.replace(QLatin1String("::"), QLatin1String("_")); + return result + QLatin1String("Wrapper"); } QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass) @@ -394,7 +361,8 @@ QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClas QString fullClassName = metaClass->name(); const AbstractMetaClass *enclosing = metaClass->enclosingClass(); while (enclosing) { - fullClassName.prepend(enclosing->name() + QLatin1Char('.')); + if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry())) + fullClassName.prepend(enclosing->name() + QLatin1Char('.')); enclosing = enclosing->enclosingClass(); } fullClassName.prepend(packageName() + QLatin1Char('.')); @@ -821,7 +789,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry *type) baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type)); } else if (type->isContainer()) { const auto *ctype = static_cast<const ContainerTypeEntry *>(type); - switch (ctype->type()) { + switch (ctype->containerKind()) { case ContainerTypeEntry::ListContainer: case ContainerTypeEntry::StringListContainer: case ContainerTypeEntry::LinkedListContainer: @@ -1196,10 +1164,11 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType return QLatin1String("PyObject_Check"); return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); } - if (metaType->typeEntry()->isContainer()) { + auto typeEntry = metaType->typeEntry(); + if (typeEntry->isContainer()) { QString typeCheck = QLatin1String("Shiboken::Conversions::"); - ContainerTypeEntry::Type type = - static_cast<const ContainerTypeEntry *>(metaType->typeEntry())->type(); + ContainerTypeEntry::ContainerKind type = + static_cast<const ContainerTypeEntry *>(typeEntry)->containerKind(); if (type == ContainerTypeEntry::ListContainer || type == ContainerTypeEntry::StringListContainer || type == ContainerTypeEntry::LinkedListContainer @@ -1238,7 +1207,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType } return typeCheck; } - return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); + return cpythonCheckFunction(typeEntry, genericNumberType); } QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type, bool genericNumberType) @@ -1486,6 +1455,16 @@ void ShibokenGenerator::writeFunctionArguments(QTextStream &s, } } +GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) const +{ + GeneratorContext result = Generator::contextForClass(c); + if (shouldGenerateCppWrapper(c)) { + result.m_type = GeneratorContext::WrappedClass; + result.m_wrappername = wrapperName(c); + } + return result; +} + QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction *func, Options options) const { QString modifiedReturnType = QString(func->typeReplaced(0)); @@ -1569,16 +1548,34 @@ void ShibokenGenerator::writeUnusedVariableCast(QTextStream &s, const QString &v s << INDENT << "SBK_UNUSED(" << variableName<< ")\n"; } +static bool filterFunction(const AbstractMetaFunction *func, bool avoidProtectedHack) +{ + switch (func->functionType()) { + case AbstractMetaFunction::DestructorFunction: + case AbstractMetaFunction::SignalFunction: + case AbstractMetaFunction::GetAttroFunction: + case AbstractMetaFunction::SetAttroFunction: + return false; + default: + break; + } + if (func->usesRValueReferences()) + return false; + if (func->isModifiedRemoved() && !func->isAbstract() + && (!avoidProtectedHack || !func->isProtected())) { + return false; + } + return true; +} + AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass *metaClass) { AbstractMetaFunctionList result; const AbstractMetaFunctionList &funcs = metaClass->functions(); + result.reserve(funcs.size()); for (AbstractMetaFunction *func : funcs) { - if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() - || (func->isModifiedRemoved() && !func->isAbstract() - && (!avoidProtectedHack() || !func->isProtected()))) - continue; - result << func; + if (filterFunction(func, avoidProtectedHack())) + result.append(func); } return result; } @@ -1663,17 +1660,24 @@ QString ShibokenGenerator::getCodeSnippets(const CodeSnipList &codeSnips, } return code; } -void ShibokenGenerator::processCodeSnip(QString &code, const AbstractMetaClass *context) + +void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorContext &context) { - if (context) { - // Replace template variable by the Python Type object - // for the class context in which the variable is used. - code.replace(QLatin1String("%PYTHONTYPEOBJECT"), - cpythonTypeName(context) + QLatin1String("->type")); - code.replace(QLatin1String("%TYPE"), wrapperName(context)); - code.replace(QLatin1String("%CPPTYPE"), context->name()); - } + auto metaClass = context.metaClass(); + // Replace template variable by the Python Type object + // for the class context in which the variable is used. + code.replace(QLatin1String("%PYTHONTYPEOBJECT"), + cpythonTypeName(metaClass) + QLatin1String("->type")); + const QString className = context.useWrapper() + ? context.wrapperName() : metaClass->qualifiedCppName(); + code.replace(QLatin1String("%TYPE"), className); + code.replace(QLatin1String("%CPPTYPE"), metaClass->name()); + processCodeSnip(code); +} + +void ShibokenGenerator::processCodeSnip(QString &code) +{ // replace "toPython" converters replaceConvertToPythonTypeSystemVariable(code); @@ -1739,19 +1743,33 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl return argReplacements; } -void ShibokenGenerator::writeCodeSnips(QTextStream &s, +void ShibokenGenerator::writeClassCodeSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language, - const AbstractMetaClass *context) + const GeneratorContext &context) +{ + QString code = getCodeSnippets(codeSnips, position, language); + if (code.isEmpty()) + return; + processClassCodeSnip(code, context); + s << INDENT << "// Begin code injection\n"; + s << code; + s << INDENT << "// End of code injection\n\n"; +} + +void ShibokenGenerator::writeCodeSnips(QTextStream &s, + const CodeSnipList &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language) { QString code = getCodeSnippets(codeSnips, position, language); if (code.isEmpty()) return; - processCodeSnip(code, context); + processCodeSnip(code); s << INDENT << "// Begin code injection\n"; s << code; - s << INDENT << "// End of code injection\n"; + s << INDENT << "// End of code injection\n\n"; } void ShibokenGenerator::writeCodeSnips(QTextStream &s, @@ -1978,7 +1996,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream &s, processCodeSnip(code); s << INDENT << "// Begin code injection\n"; s << code; - s << INDENT << "// End of code injection\n"; + s << INDENT << "// End of code injection\n\n"; } // Returns true if the string is an expression, @@ -2137,13 +2155,17 @@ bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction *func) return false; } -bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction *func) +bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &context, + const AbstractMetaFunction *func) { QString funcCall = func->originalName() + QLatin1Char('('); QString wrappedCtorCall; if (func->isConstructor()) { funcCall.prepend(QLatin1String("new ")); - wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); + const auto owner = func->ownerClass(); + const QString className = context.useWrapper() + ? context.wrapperName() : owner->qualifiedCppName(); + wrappedCtorCall = QLatin1String("new ") + className + QLatin1Char('('); } CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); for (const CodeSnip &snip : qAsConst(snips)) { @@ -2213,10 +2235,18 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A } else { if (getGeneratorClassInfo(metaClass).needsGetattroFunction) result |= AttroCheckFlag::GetattroOverloads; + if (metaClass->queryFirstFunction(metaClass->functions(), + AbstractMetaClass::GetAttroFunction)) { + result |= AttroCheckFlag::GetattroUser; + } if (usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject")) result |= AttroCheckFlag::SetattroQObject; if (useOverrideCaching(metaClass)) result |= AttroCheckFlag::SetattroMethodOverride; + if (metaClass->queryFirstFunction(metaClass->functions(), + AbstractMetaClass::SetAttroFunction)) { + result |= AttroCheckFlag::SetattroUser; + } // PYSIDE-1255: If setattro is generated for a class inheriting // QObject, the property code needs to be generated, too. if ((result & AttroCheckFlag::SetattroMask) != 0 @@ -2394,11 +2424,20 @@ static void dumpFunction(AbstractMetaFunctionList lst) static bool isGroupable(const AbstractMetaFunction *func) { - if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract())) + switch (func->functionType()) { + case AbstractMetaFunction::DestructorFunction: + case AbstractMetaFunction::SignalFunction: + case AbstractMetaFunction::GetAttroFunction: + case AbstractMetaFunction::SetAttroFunction: + return false; + default: + break; + } + if (func->isModifiedRemoved() && !func->isAbstract()) return false; // weird operator overloads if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? - return false;; + return false; return true; } @@ -2518,7 +2557,9 @@ Generator::OptionDescriptions ShibokenGenerator::options() const "(USE WITH CAUTION!)")) << qMakePair(QLatin1String(USE_ISNULL_AS_NB_NONZERO), QLatin1String("If a class have an isNull() const method, it will be used to compute\n" - "the value of boolean casts")); + "the value of boolean casts")) + << qMakePair(QLatin1String(WRAPPER_DIAGNOSTICS), + QLatin1String("Generate diagnostic code around wrappers")); } bool ShibokenGenerator::handleOption(const QString &key, const QString & /* value */) @@ -2535,6 +2576,8 @@ bool ShibokenGenerator::handleOption(const QString &key, const QString & /* valu return (m_useIsNullAsNbNonZero = true); if (key == QLatin1String(AVOID_PROTECTED_HACK)) return (m_avoidProtectedHack = true); + if (key == QLatin1String(WRAPPER_DIAGNOSTICS)) + return (m_wrapperDiagnostics = true); return false; } @@ -2599,13 +2642,19 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString & QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP["); int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); int start = 0; + QString errorMessage; while ((start = code.indexOf(convMacro, start)) != -1) { int end = code.indexOf(QLatin1Char(']'), start); start += offset; if (code.at(start) != QLatin1Char('%')) { QString typeString = code.mid(start, end - start); - AbstractMetaType *type = buildAbstractMetaTypeFromString(typeString); - addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + if (AbstractMetaType *type = + buildAbstractMetaTypeFromString(typeString, &errorMessage)) { + addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + } else { + qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__, + qPrintable(typeString), qPrintable(errorMessage)); + } } start = end; } @@ -2778,7 +2827,7 @@ void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream &s, const } else { const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); qCWarning(lcShiboken()).noquote() << message; - s << ";\n#error " << message << endl; + s << ";\n#error " << message << Qt::endl; } } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index 24c1374ae..d8259d245 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -69,10 +69,12 @@ public: None = 0x0, GetattroOverloads = 0x01, GetattroSmartPointer = 0x02, + GetattroUser = 0x04, // Injected code GetattroMask = 0x0F, SetattroQObject = 0x10, SetattroSmartPointer = 0x20, SetattroMethodOverride = 0x40, + SetattroUser = 0x80, // Injected code SetattroMask = 0xF0, }; Q_DECLARE_FLAGS(AttroCheck, AttroCheckFlag); @@ -105,6 +107,8 @@ protected: const AbstractMetaFunction *func, Options options = NoOption) const override; + GeneratorContext contextForClass(const AbstractMetaClass *c) const override; + /** * Returns a map with all functions grouped, the function name is used as key. * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} @@ -122,11 +126,15 @@ protected: AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen); /// Write user's custom code snippets at class or module level. + void writeClassCodeSnips(QTextStream &s, + const QVector<CodeSnip> & codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const GeneratorContext &context); void writeCodeSnips(QTextStream &s, const QVector<CodeSnip> & codeSnips, TypeSystem::CodeSnipPosition position, - TypeSystem::Language language, - const AbstractMetaClass *context = nullptr); + TypeSystem::Language language); /// Write user's custom code snippets at function level. void writeCodeSnips(QTextStream &s, const QVector<CodeSnip> & codeSnips, @@ -136,7 +144,8 @@ protected: const AbstractMetaArgument *lastArg = nullptr); /// Replaces variables for the user's custom code at global or class level. - void processCodeSnip(QString &code, const AbstractMetaClass *context = nullptr); + void processCodeSnip(QString &code); + void processClassCodeSnip(QString &code, const GeneratorContext &context); /** * Verifies if any of the function's code injections of the "native" @@ -153,7 +162,8 @@ protected: * \param func the function to check * \return true if the function's code snippets call the wrapped C++ function */ - bool injectedCodeCallsCppFunction(const AbstractMetaFunction *func); + bool injectedCodeCallsCppFunction(const GeneratorContext &context, + const AbstractMetaFunction *func); /** * Verifies if any of the function's code injections of the "native" class makes a @@ -219,16 +229,14 @@ protected: /// Adds enums eligible for generation from classes/namespaces marked not to be generated. static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass); - /// Returns the enclosing class for an enum, or nullptr if it should be global. - const AbstractMetaClass *getProperEnclosingClassForEnum(const AbstractMetaEnum *metaEnum); QString wrapperName(const AbstractMetaClass *metaClass) const; - QString wrapperName(const AbstractMetaType *metaType) const; - QString wrapperName(const TypeEntry *type) const; QString fullPythonClassName(const AbstractMetaClass *metaClass); QString fullPythonFunctionName(const AbstractMetaFunction *func); + bool wrapperDiagnostics() const { return m_wrapperDiagnostics; } + static QString protectedEnumSurrogateName(const AbstractMetaEnum *metaEnum); static QString protectedFieldGetterName(const AbstractMetaField *field); static QString protectedFieldSetterName(const AbstractMetaField *field); @@ -550,6 +558,7 @@ private: bool m_verboseErrorMessagesDisabled = false; bool m_useIsNullAsNbNonZero = false; bool m_avoidProtectedHack = false; + bool m_wrapperDiagnostics = false; using AbstractMetaTypeCache = QHash<QString, AbstractMetaType *>; AbstractMetaTypeCache m_metaTypeFromStringCache; diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index a38da8d89..dee5dbd21 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -14,7 +14,7 @@ macro(get_numpy_location) break" OUTPUT_VARIABLE PYTHON_NUMPY_LOCATION OUTPUT_STRIP_TRAILING_WHITESPACE) - message("PYTHON_NUMPY_LOCATION: " ${PYTHON_NUMPY_LOCATION}) + message(STATUS "PYTHON_NUMPY_LOCATION: " ${PYTHON_NUMPY_LOCATION}) endmacro() option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 78f4cbe8b..d7184569b 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -59,6 +59,8 @@ #include "qapp_macro.h" #include "voidptr.h" +#include <iostream> + #if defined(__APPLE__) #include <dlfcn.h> #endif @@ -484,7 +486,7 @@ void SbkObjectTypeDealloc(PyObject *pyObj) } } -PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds) +static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { // Check if all bases are new style before calling type.tp_new // Was causing gc assert errors in test_bug704.py when @@ -511,7 +513,8 @@ PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *k #ifndef IS_PY3K if (PyClass_Check(baseType)) { PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. " - "PySide only support multiple inheritance from python new style class.", metatype->tp_name); + "PySide only supports multiple inheritance from Python new style classes.", + metatype->tp_name); return 0; } #endif @@ -577,7 +580,6 @@ PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *k if (PepType_SOTP(base)->subtype_init) PepType_SOTP(base)->subtype_init(newType, args, kwds); } - return reinterpret_cast<PyObject *>(newType); } @@ -729,35 +731,6 @@ bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visi return result; } -bool importModule(const char *moduleName, PyTypeObject *** cppApiPtr) -{ - PyObject *sysModules = PyImport_GetModuleDict(); - PyObject *module = PyDict_GetItemString(sysModules, moduleName); - if (!module) { - module = PyImport_ImportModule(moduleName); - if (!module) - return false; - } else { - Py_INCREF(module); - } - - Shiboken::AutoDecRef cppApi(PyObject_GetAttrString(module, "_Cpp_Api")); - Py_DECREF(module); - - if (cppApi.isNull()) - return false; - -#ifdef IS_PY3K - if (PyCapsule_CheckExact(cppApi)) - *cppApiPtr = reinterpret_cast<PyTypeObject **>(PyCapsule_GetPointer(cppApi, nullptr)); -#else - // Python 2.6 doesn't have PyCapsule API, so let's keep usign PyCObject on all Python 2.x - if (PyCObject_Check(cppApi)) - *cppApiPtr = reinterpret_cast<PyTypeObject **>(PyCObject_AsVoidPtr(cppApi)); -#endif - return true; -} - // Wrapper metatype and base type ---------------------------------------------------------- HierarchyVisitor::HierarchyVisitor() = default; @@ -984,8 +957,11 @@ introduceWrapperType(PyObject *enclosingObject, } } // PYSIDE-510: Here is the single change to support signatures. - if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 0) + if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to SbkSpecial_Type_Ready() failing\n"; return nullptr; + } initPrivateData(type); auto sotp = PepType_SOTP(type); @@ -1001,7 +977,13 @@ introduceWrapperType(PyObject *enclosingObject, // PyModule_AddObject steals type's reference. Py_INCREF(ob_type); - return PyModule_AddObject(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; + if (PyModule_AddObject(enclosingObject, typeName, ob_type) != 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to PyModule_AddObject(enclosingObject=" + << enclosingObject << ",ob_type=" << ob_type << ") failing\n"; + return nullptr; + } + return type; } void setSubTypeInitHook(SbkObjectType *type, SubTypeInitHook func) @@ -1456,11 +1438,6 @@ PyObject *newObject(SbkObjectType *instanceType, return reinterpret_cast<PyObject *>(self); } -void destroy(SbkObject *self) -{ - destroy(self, nullptr); -} - void destroy(SbkObject *self, void *cppData) { // Skip if this is called with NULL pointer this can happen in derived classes diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h index 4132b5cc5..7248103cc 100644 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ b/sources/shiboken2/libshiboken/basewrapper.h @@ -86,9 +86,6 @@ typedef void *(*SpecialCastFunction)(void *, SbkObjectType *); typedef SbkObjectType *(*TypeDiscoveryFunc)(void *, SbkObjectType *); typedef void *(*TypeDiscoveryFuncV2)(void *, SbkObjectType *); -typedef void *(*ExtendedToCppFunc)(PyObject *); // DEPRECATED. -typedef bool (*ExtendedIsConvertibleFunc)(PyObject *); // DEPRECATED. - // Used in userdata dealloc function typedef void (*DeleteUserDataFunc)(void *); @@ -144,11 +141,6 @@ void callCppDestructor(void *cptr) delete reinterpret_cast<T *>(cptr); } -/** - * Shiboken::importModule is DEPRECATED. Use Shiboken::Module::import() instead. - */ -SBK_DEPRECATED(LIBSHIBOKEN_API bool importModule(const char *moduleName, PyTypeObject *** cppApiPtr)); - // setErrorAboutWrongArguments now gets overload info from the signature module. LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject *args, const char *funcName); @@ -426,9 +418,6 @@ LIBSHIBOKEN_API void invalidate(PyObject *pyobj); */ LIBSHIBOKEN_API void makeValid(SbkObject *self); -/// \deprecated Use destroy(SbkObject *, void *) -SBK_DEPRECATED(LIBSHIBOKEN_API void destroy(SbkObject *self)); - /** * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership */ diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp index 1f18ed60a..1ab8dd089 100644 --- a/sources/shiboken2/libshiboken/bindingmanager.cpp +++ b/sources/shiboken2/libshiboken/bindingmanager.cpp @@ -318,11 +318,6 @@ void BindingManager::addClassInheritance(SbkObjectType *parent, SbkObjectType *c m_d->classHierarchy.addEdge(parent, child); } -SbkObjectType *BindingManager::resolveType(void *cptr, SbkObjectType *type) -{ - return resolveType(&cptr, type); -} - SbkObjectType *BindingManager::resolveType(void **cptr, SbkObjectType *type) { SbkObjectType *identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); diff --git a/sources/shiboken2/libshiboken/bindingmanager.h b/sources/shiboken2/libshiboken/bindingmanager.h index bfcbdc79b..ba5535347 100644 --- a/sources/shiboken2/libshiboken/bindingmanager.h +++ b/sources/shiboken2/libshiboken/bindingmanager.h @@ -77,12 +77,6 @@ public: void addClassInheritance(SbkObjectType *parent, SbkObjectType *child); /** - * \deprecated Use \fn resolveType(void **, SbkObjectType *), this version is broken when used with multiple inheritance - * because the \p cptr pointer of the discovered type may be different of the given \p cptr in case - * of multiple inheritance - */ - SBK_DEPRECATED(SbkObjectType *resolveType(void *cptr, SbkObjectType *type)); - /** * Try to find the correct type of *cptr knowing that it's at least of type \p type. * In case of multiple inheritance this function may change the contents of cptr. * \param cptr a pointer to a pointer to the instance of type \p type diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp index 013080b6e..b0f909d39 100644 --- a/sources/shiboken2/libshiboken/helper.cpp +++ b/sources/shiboken2/libshiboken/helper.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -40,17 +40,128 @@ #include "helper.h" #include "sbkstring.h" #include "sbkstaticstrings.h" + +#include <iomanip> +#include <iostream> + #include <stdarg.h> #ifdef _WIN32 +# ifndef NOMINMAX +# define NOMINMAX +# endif # include <windows.h> #else # include <pthread.h> #endif +#include <algorithm> + +static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str) +{ + if (obj) { + str << '"' << obj->tp_name << "\", 0x" << std::hex + << obj->tp_flags << std::dec; + if (obj->tp_flags & Py_TPFLAGS_HEAPTYPE) + str << " [heaptype]"; + if (obj->tp_flags & Py_TPFLAGS_BASETYPE) + str << " [base]"; + if (obj->tp_flags & Py_TPFLAGS_HAVE_GC) + str << " [gc]"; + if (obj->tp_flags & Py_TPFLAGS_LONG_SUBCLASS) + str << " [long]"; + if (obj->tp_flags & Py_TPFLAGS_LIST_SUBCLASS) + str << " [list]"; + if (obj->tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS) + str << " [tuple]"; + if (obj->tp_flags & Py_TPFLAGS_BYTES_SUBCLASS) + str << " [bytes]"; + if (obj->tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS) + str << " [unicode]"; + if (obj->tp_flags & Py_TPFLAGS_DICT_SUBCLASS) + str << " [dict]"; + if (obj->tp_flags & Py_TPFLAGS_TYPE_SUBCLASS) + str << " [type]"; + if (obj->tp_flags & Py_TPFLAGS_IS_ABSTRACT) + str << " [abstract]"; + } else { + str << '0'; + } +} + +static void formatPyObject(PyObject *obj, std::ostream &str); + +static void formatPySequence(PyObject *obj, std::ostream &str) +{ + const Py_ssize_t size = PySequence_Size(obj); + const Py_ssize_t printSize = std::min(size, Py_ssize_t(5)); + str << size << " <"; + for (Py_ssize_t i = 0; i < printSize; ++i) { + if (i) + str << ", "; + str << '('; + PyObject *item = PySequence_GetItem(obj, i); + formatPyObject(item, str); + str << ')'; + Py_XDECREF(item); + } + if (printSize < size) + str << ",..."; + str << '>'; +} + +static void formatPyObject(PyObject *obj, std::ostream &str) +{ + if (obj) { + formatPyTypeObject(obj->ob_type, str); + str << ", "; + if (PyLong_Check(obj)) + str << PyLong_AsLong(obj); + else if (PyFloat_Check(obj)) + str << PyFloat_AsDouble(obj); +#ifdef IS_PY3K + else if (PyUnicode_Check(obj)) + str << '"' << _PepUnicode_AsString(obj) << '"'; +#else + else if (PyString_Check(obj)) + str << '"' << PyString_AsString(obj) << '"'; +#endif + else if (PySequence_Check(obj)) + formatPySequence(obj, str); + else + str << "<unknown>"; + } else { + str << '0'; + } +} + namespace Shiboken { +debugPyObject::debugPyObject(PyObject *o) : m_object(o) +{ +} + +debugPyTypeObject::debugPyTypeObject(const PyTypeObject *o) : m_object(o) +{ +} + +std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o) +{ + str << "PyTypeObject("; + formatPyTypeObject(o.m_object, str); + str << ')'; + return str; +} + +std::ostream &operator<<(std::ostream &str, const debugPyObject &o) +{ + str << "PyObject("; + formatPyObject(o.m_object, str); + str << ')'; + return str; +} + // PySide-510: Changed from PySequence to PyList, which is correct. bool listToArgcArgv(PyObject *argList, int *argc, char ***argv, const char *defaultAppName) { @@ -125,7 +236,7 @@ int warning(PyObject *category, int stacklevel, const char *format, ...) { va_list args; va_start(args, format); -#if _WIN32 +#ifdef _WIN32 va_list args2 = args; #else va_list args2; diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h index 14aae8028..7e46f3d93 100644 --- a/sources/shiboken2/libshiboken/helper.h +++ b/sources/shiboken2/libshiboken/helper.h @@ -44,6 +44,8 @@ #include "shibokenmacros.h" #include "autodecref.h" +#include <iosfwd> + #define SBK_UNUSED(x) (void)(x); namespace Shiboken @@ -99,6 +101,24 @@ LIBSHIBOKEN_API ThreadId mainThreadId(); */ LIBSHIBOKEN_API int warning(PyObject *category, int stacklevel, const char *format, ...); +struct LIBSHIBOKEN_API debugPyObject +{ + explicit debugPyObject(PyObject *o); + + PyObject *m_object; +}; + +struct LIBSHIBOKEN_API debugPyTypeObject +{ + explicit debugPyTypeObject(const PyTypeObject *o); + + const PyTypeObject *m_object; +}; + +LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyObject &o); +LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o); + } // namespace Shiboken + #endif // HELPER_H diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp index f07cac613..5e0053e2e 100644 --- a/sources/shiboken2/libshiboken/pep384impl.cpp +++ b/sources/shiboken2/libshiboken/pep384impl.cpp @@ -668,6 +668,22 @@ PyImport_GetModule(PyObject *name) } #endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API) + +/***************************************************************************** + * + * Python 2 incompatibilities + * + * This is incompatibly implemented as macro in Python 2. + */ +#if PY_VERSION_HEX < 0x03000000 + +PyObject *PepMapping_Items(PyObject *o) +{ + return PyObject_CallMethod(o, const_cast<char *>("items"), NULL); +} + +#endif + /***************************************************************************** * * Extra support for name mangling diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h index 541b0e775..2bfe52254 100644 --- a/sources/shiboken2/libshiboken/pep384impl.h +++ b/sources/shiboken2/libshiboken/pep384impl.h @@ -533,6 +533,18 @@ LIBSHIBOKEN_API PyObject *PyImport_GetModule(PyObject *name); /***************************************************************************** * + * Python 2 incompatibilities + * + * This is incompatibly implemented as macro in Python 2. + */ +#if PY_VERSION_HEX < 0x03000000 +extern LIBSHIBOKEN_API PyObject *PepMapping_Items(PyObject *o); +#else +#define PepMapping_Items PyMapping_Items +#endif + +/***************************************************************************** + * * Runtime support for Python 3.8 incompatibilities * */ diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp index 36f2f48f9..369b264e7 100644 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ b/sources/shiboken2/libshiboken/sbkenum.cpp @@ -608,11 +608,16 @@ newItem(PyTypeObject *enumType, long itemValue, const char *itemName) enumObj->ob_value = itemValue; if (newValue) { - PyObject *values = PyDict_GetItem(enumType->tp_dict, Shiboken::PyName::values()); - if (!values) { - values = PyDict_New(); - PyDict_SetItem(enumType->tp_dict, Shiboken::PyName::values(), values); - Py_DECREF(values); // ^ values still alive, because setitem increfs it + auto dict = enumType->tp_dict; // Note: 'values' is borrowed + PyObject *values = PyDict_GetItemWithError(dict, Shiboken::PyName::values()); + if (values == nullptr) { + if (PyErr_Occurred()) + return nullptr; + Shiboken::AutoDecRef new_values(values = PyDict_New()); + if (values == nullptr) + return nullptr; + if (PyDict_SetItem(dict, Shiboken::PyName::values(), values) < 0) + return nullptr; } PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject *>(enumObj)); } @@ -720,11 +725,11 @@ newTypeWithName(const char *name, { // Careful: SbkType_FromSpec does not allocate the string. PyType_Slot newslots[99] = {}; // enough but not too big for the stack - auto *newspec = new PyType_Spec; - newspec->name = strdup(name); - newspec->basicsize = SbkNewType_spec.basicsize; - newspec->itemsize = SbkNewType_spec.itemsize; - newspec->flags = SbkNewType_spec.flags; + PyType_Spec newspec; + newspec.name = strdup(name); + newspec.basicsize = SbkNewType_spec.basicsize; + newspec.itemsize = SbkNewType_spec.itemsize; + newspec.flags = SbkNewType_spec.flags; // we must append all the number methods, so rebuild everything: int idx = 0; while (SbkNewType_slots[idx].slot) { @@ -734,8 +739,8 @@ newTypeWithName(const char *name, } if (numbers_fromFlag) copyNumberMethods(numbers_fromFlag, newslots, &idx); - newspec->slots = newslots; - auto *type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(newspec)); + newspec.slots = newslots; + auto *type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&newspec)); Py_TYPE(type) = SbkEnumType_TypeF(); auto *enumType = reinterpret_cast<SbkEnumType *>(type); diff --git a/sources/shiboken2/libshiboken/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h index 9dd1e712e..6755e945d 100644 --- a/sources/shiboken2/libshiboken/sbkpython.h +++ b/sources/shiboken2/libshiboken/sbkpython.h @@ -41,6 +41,7 @@ #define SBKPYTHON_H #include "sbkversion.h" +#define PyEnumMeta_Check(x) (strcmp(Py_TYPE(x)->tp_name, "EnumMeta") == 0) // Qt's "slots" macro collides with the "slots" member variables // used in some Python structs. For compilers that support push_macro, diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp index c19665176..541d74918 100644 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp @@ -55,11 +55,15 @@ namespace PyName { STATIC_STRING_IMPL(dumps, "dumps") STATIC_STRING_IMPL(loads, "loads") STATIC_STRING_IMPL(result, "result") +STATIC_STRING_IMPL(value, "value") STATIC_STRING_IMPL(values, "values") // Internal: STATIC_STRING_IMPL(classmethod, "classmethod") +STATIC_STRING_IMPL(co_name, "co_name") STATIC_STRING_IMPL(compile, "compile"); +STATIC_STRING_IMPL(f_code, "f_code") +STATIC_STRING_IMPL(f_lineno, "f_lineno") STATIC_STRING_IMPL(function, "function") STATIC_STRING_IMPL(marshal, "marshal") STATIC_STRING_IMPL(method, "method") @@ -73,6 +77,7 @@ namespace PyMagicName { STATIC_STRING_IMPL(class_, "__class__") STATIC_STRING_IMPL(ecf, "__ecf__") STATIC_STRING_IMPL(file, "__file__") +STATIC_STRING_IMPL(members, "__members__") STATIC_STRING_IMPL(module, "__module__") STATIC_STRING_IMPL(name, "__name__") STATIC_STRING_IMPL(qualname, "__qualname__") diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h index 07d6cc60a..4078d163c 100644 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.h +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h @@ -48,9 +48,13 @@ namespace Shiboken // Some often-used strings namespace PyName { +LIBSHIBOKEN_API PyObject *co_name(); LIBSHIBOKEN_API PyObject *dumps(); +LIBSHIBOKEN_API PyObject *f_code(); +LIBSHIBOKEN_API PyObject *f_lineno(); LIBSHIBOKEN_API PyObject *loads(); LIBSHIBOKEN_API PyObject *result(); +LIBSHIBOKEN_API PyObject *value(); LIBSHIBOKEN_API PyObject *values(); } // namespace PyName @@ -59,6 +63,7 @@ namespace PyMagicName LIBSHIBOKEN_API PyObject *class_(); LIBSHIBOKEN_API PyObject *ecf(); LIBSHIBOKEN_API PyObject *file(); +LIBSHIBOKEN_API PyObject *members(); LIBSHIBOKEN_API PyObject *module(); LIBSHIBOKEN_API PyObject *name(); LIBSHIBOKEN_API PyObject *qualname(); diff --git a/sources/shiboken2/shiboken_version.py b/sources/shiboken2/shiboken_version.py index 0e0943143..f5ef03613 100644 --- a/sources/shiboken2/shiboken_version.py +++ b/sources/shiboken2/shiboken_version.py @@ -38,13 +38,13 @@ ############################################################################# major_version = "5" -minor_version = "14" -patch_version = "2" +minor_version = "15" +patch_version = "0" # For example: "a", "b", "rc" # (which means "alpha", "beta", "release candidate"). # An empty string means the generated package will be an official release. -pre_release_version_type = "a" +release_version_type = "a" # For example: "1", "2" (which means "beta1", "beta2", if type is "b"). pre_release_version = "1" @@ -52,4 +52,4 @@ pre_release_version = "1" if __name__ == '__main__': # Used by CMake. print('{0};{1};{2};{3};{4}'.format(major_version, minor_version, patch_version, - pre_release_version_type, pre_release_version)) + release_version_type, pre_release_version)) diff --git a/sources/shiboken2/tests/CMakeLists.txt b/sources/shiboken2/tests/CMakeLists.txt index 375215369..2ba951de1 100644 --- a/sources/shiboken2/tests/CMakeLists.txt +++ b/sources/shiboken2/tests/CMakeLists.txt @@ -1,5 +1,7 @@ +cmake_minimum_required(VERSION 3.1) + if(BUILD_TESTS) - find_package(Qt5Test 5.12 REQUIRED) + find_package(Qt${QT_MAJOR_VERSION}Test 5.12 REQUIRED) endif() add_subdirectory(libminimal) @@ -42,24 +44,20 @@ if(NOT CTEST_TESTING_TIMEOUT) set(CTEST_TESTING_TIMEOUT 60) endif() -if(CMAKE_VERSION VERSION_LESS 2.8) - message("CMake version greater than 2.8 necessary to run tests") -else() - get_filename_component(BUILD_DIR "${libminimal_BINARY_DIR}" DIRECTORY) - get_filename_component(BUILD_DIR "${BUILD_DIR}" DIRECTORY) - get_filename_component(BUILD_DIR "${BUILD_DIR}" DIRECTORY) - foreach(test_file ${TEST_FILES}) - string(REGEX MATCH "/([^/]+)(binding|module)/([^/]+)_test.py" tmp ${test_file}) - set(test_name "${CMAKE_MATCH_1}_${CMAKE_MATCH_3}") - list(FIND test_blacklist ${test_name} expect_fail) - add_test(${test_name} ${PYTHON_EXECUTABLE} ${test_file}) - set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "BUILD_DIR=${BUILD_DIR}") - set_tests_properties(${test_name} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT}) - if (${expect_fail} GREATER -1) - set_tests_properties(${test_name} PROPERTIES WILL_FAIL TRUE) - endif() - endforeach() -endif() +get_filename_component(BUILD_DIR "${libminimal_BINARY_DIR}" DIRECTORY) +get_filename_component(BUILD_DIR "${BUILD_DIR}" DIRECTORY) +get_filename_component(BUILD_DIR "${BUILD_DIR}" DIRECTORY) +foreach(test_file ${TEST_FILES}) + string(REGEX MATCH "/([^/]+)(binding|module)/([^/]+)_test.py" tmp ${test_file}) + set(test_name "${CMAKE_MATCH_1}_${CMAKE_MATCH_3}") + list(FIND test_blacklist ${test_name} expect_fail) + add_test(${test_name} ${PYTHON_EXECUTABLE} ${test_file}) + set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "BUILD_DIR=${BUILD_DIR}") + set_tests_properties(${test_name} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT}) + if (${expect_fail} GREATER -1) + set_tests_properties(${test_name} PROPERTIES WILL_FAIL TRUE) + endif() +endforeach() add_subdirectory(dumpcodemodel) diff --git a/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt index 7c6d60fe2..5c5e2c7b0 100644 --- a/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt +++ b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt @@ -3,4 +3,4 @@ add_executable(dumpcodemodel main.cpp) target_include_directories(dumpcodemodel PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${apiextractor_SOURCE_DIR}) -target_link_libraries(dumpcodemodel PUBLIC apiextractor Qt5::Core) +target_link_libraries(dumpcodemodel PUBLIC apiextractor Qt${QT_MAJOR_VERSION}::Core) diff --git a/sources/shiboken2/tests/dumpcodemodel/main.cpp b/sources/shiboken2/tests/dumpcodemodel/main.cpp index 52d64be94..37c964fc0 100644 --- a/sources/shiboken2/tests/dumpcodemodel/main.cpp +++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp @@ -43,6 +43,8 @@ #include <algorithm> #include <iterator> +static bool optJoinNamespaces = false; + static inline QString languageLevelDescription() { return QLatin1String("C++ Language level (c++11..c++17, default=") @@ -69,7 +71,6 @@ static const char *primitiveTypes[] = { static inline QString nameAttribute() { return QStringLiteral("name"); } -static void formatXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp); static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass); static void formatXmlEnum(QXmlStreamWriter &writer, const EnumModelItem &en) @@ -79,10 +80,16 @@ static void formatXmlEnum(QXmlStreamWriter &writer, const EnumModelItem &en) writer.writeEndElement(); } +static bool useClass(const ClassModelItem &c) +{ + return c->classType() != CodeModel::Union && c->templateParameters().isEmpty() + && !c->name().isEmpty(); // No anonymous structs +} + static void formatXmlScopeMembers(QXmlStreamWriter &writer, const ScopeModelItem &nsp) { for (const auto &klass : nsp->classes()) { - if (klass->classType() != CodeModel::Union && klass->templateParameters().isEmpty()) + if (useClass(klass)) formatXmlClass(writer, klass); } for (const auto &en : nsp->enums()) @@ -95,12 +102,20 @@ static bool isPublicCopyConstructor(const FunctionModelItem &f) && f->accessPolicy() == CodeModel::Public && !f->isDeleted(); } +static void formatXmlLocationComment(QXmlStreamWriter &writer, const CodeModelItem &i) +{ + QString comment; + QTextStream(&comment) << ' ' << i->fileName() << ':' << i->startLine() << ' '; + writer.writeComment(comment); +} + static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass) { // Heuristics for value types: check on public copy constructors. const auto functions = klass->functions(); const bool isValueType = std::any_of(functions.cbegin(), functions.cend(), isPublicCopyConstructor); + formatXmlLocationComment(writer, klass); writer.writeStartElement(isValueType ? QStringLiteral("value-type") : QStringLiteral("object-type")); writer.writeAttribute(nameAttribute(), klass->name()); @@ -108,10 +123,51 @@ static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass writer.writeEndElement(); } +// Check whether a namespace is relevant for type system +// output, that is, has non template classes, functions or enumerations. +static bool hasMembers(const NamespaceModelItem &nsp) +{ + if (!nsp->namespaces().isEmpty() || !nsp->enums().isEmpty() + || !nsp->functions().isEmpty()) { + return true; + } + const auto classes = nsp->classes(); + return std::any_of(classes.cbegin(), classes.cend(), useClass); +} + +static void startXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp) +{ + formatXmlLocationComment(writer, nsp); + writer.writeStartElement(QStringLiteral("namespace-type")); + writer.writeAttribute(nameAttribute(), nsp->name()); +} + static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceModelItem &nsp) { - for (const auto &nested : nsp->namespaces()) - formatXmlNamespace(writer, nested); + auto nestedNamespaces = nsp->namespaces(); + for (int i = nestedNamespaces.size() - 1; i >= 0; --i) { + if (!hasMembers(nestedNamespaces.at(i))) + nestedNamespaces.removeAt(i); + } + while (!nestedNamespaces.isEmpty()) { + auto current = nestedNamespaces.takeFirst(); + startXmlNamespace(writer, current); + formatXmlNamespaceMembers(writer, current); + if (optJoinNamespaces) { + // Write out members of identical namespaces and remove + const QString name = current->name(); + for (int i = 0; i < nestedNamespaces.size(); ) { + if (nestedNamespaces.at(i)->name() == name) { + formatXmlNamespaceMembers(writer, nestedNamespaces.at(i)); + nestedNamespaces.removeAt(i); + } else { + ++i; + } + } + } + writer.writeEndElement(); + } + for (auto func : nsp->functions()) { const QString signature = func->typeSystemSignature(); if (!signature.contains(QLatin1String("operator"))) { // Skip free operators @@ -123,14 +179,6 @@ static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceM formatXmlScopeMembers(writer, nsp); } -static void formatXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp) -{ - writer.writeStartElement(QStringLiteral("namespace-type")); - writer.writeAttribute(nameAttribute(), nsp->name()); - formatXmlNamespaceMembers(writer, nsp); - writer.writeEndElement(); -} - static void formatXmlOutput(const FileModelItem &dom) { QString output; @@ -183,6 +231,10 @@ int main(int argc, char **argv) QStringLiteral("Display debug output")); parser.addOption(debugOption); + QCommandLineOption joinNamespacesOption({QStringLiteral("j"), QStringLiteral("join-namespaces")}, + QStringLiteral("Join namespaces")); + parser.addOption(joinNamespacesOption); + QCommandLineOption languageLevelOption(QStringLiteral("std"), languageLevelDescription(), QStringLiteral("level")); @@ -211,6 +263,8 @@ int main(int argc, char **argv) } } + optJoinNamespaces = parser.isSet(joinNamespacesOption); + const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, level, 0); if (dom.isNull()) { QString message = QLatin1String("Unable to parse ") + positionalArguments.join(QLatin1Char(' ')); diff --git a/sources/shiboken2/tests/libother/CMakeLists.txt b/sources/shiboken2/tests/libother/CMakeLists.txt index 6aba91e13..d1e4c4354 100644 --- a/sources/shiboken2/tests/libother/CMakeLists.txt +++ b/sources/shiboken2/tests/libother/CMakeLists.txt @@ -5,12 +5,13 @@ number.cpp otherderived.cpp otherobjecttype.cpp othermultiplederived.cpp +smartptrtester.cpp ) add_library(libother SHARED ${libother_SRC}) target_include_directories(libother PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(libother PRIVATE LIBOTHER_BUILD) -target_link_libraries(libother PUBLIC libsample) +target_link_libraries(libother PUBLIC libsample libsmart) set_property(TARGET libother PROPERTY PREFIX "") diff --git a/sources/shiboken2/tests/libother/otherobjecttype.cpp b/sources/shiboken2/tests/libother/otherobjecttype.cpp index ca356ce94..1f782ecd8 100644 --- a/sources/shiboken2/tests/libother/otherobjecttype.cpp +++ b/sources/shiboken2/tests/libother/otherobjecttype.cpp @@ -34,3 +34,13 @@ operator<<(Collector& collector, const OtherObjectType& obj) collector << obj.identifier()*2; return collector; } + +int OtherObjectType::enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value) +{ + return static_cast<int>(value); +} + +int OtherObjectType::enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value) +{ + return static_cast<int>(value); +} diff --git a/sources/shiboken2/tests/libother/otherobjecttype.h b/sources/shiboken2/tests/libother/otherobjecttype.h index 22687c8bd..efd394347 100644 --- a/sources/shiboken2/tests/libother/otherobjecttype.h +++ b/sources/shiboken2/tests/libother/otherobjecttype.h @@ -35,11 +35,14 @@ #include "libothermacros.h" #include "objecttype.h" #include "collector.h" +#include "samplenamespace.h" -class OtherObjectType : public ObjectType + +class LIBOTHER_API OtherObjectType : public ObjectType { public: - + static int enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value); + static int enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value); }; diff --git a/sources/shiboken2/tests/libother/smartptrtester.cpp b/sources/shiboken2/tests/libother/smartptrtester.cpp new file mode 100644 index 000000000..9636c7521 --- /dev/null +++ b/sources/shiboken2/tests/libother/smartptrtester.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "smartptrtester.h" + +SharedPtr<Str> SmartPtrTester::createSharedPtrStr(const char *what) +{ + return SharedPtr<Str>(new Str(what)); +} + +std::string SmartPtrTester::valueOfSharedPtrStr(const SharedPtr<Str> &str) +{ + return str->cstring(); +} + +SharedPtr<Integer> SmartPtrTester::createSharedPtrInteger(int v) +{ + auto i = SharedPtr<Integer>(new Integer); + i->m_int = v; + return i; +} + +int SmartPtrTester::valueOfSharedPtrInteger(const SharedPtr<Integer> &v) +{ + return v->m_int; +} + +void SmartPtrTester::fiddleInt(const SharedPtr<int> &) // no binding, should not cause errors +{ +} diff --git a/sources/shiboken2/tests/libother/smartptrtester.h b/sources/shiboken2/tests/libother/smartptrtester.h new file mode 100644 index 000000000..a560bcf2f --- /dev/null +++ b/sources/shiboken2/tests/libother/smartptrtester.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMARTPTRTESTER_H +#define SMARTPTRTESTER_H + +#include "libothermacros.h" + +#include <smart.h> +#include <str.h> + +class LIBOTHER_API SmartPtrTester +{ +public: + SharedPtr<Str> createSharedPtrStr(const char *what); + std::string valueOfSharedPtrStr(const SharedPtr<Str> &); + + SharedPtr<Integer> createSharedPtrInteger(int v); + int valueOfSharedPtrInteger(const SharedPtr<Integer> &); + + void fiddleInt(const SharedPtr<int> &); +}; + +#endif // SMARTPTRTESTER_H diff --git a/sources/shiboken2/tests/libsample/CMakeLists.txt b/sources/shiboken2/tests/libsample/CMakeLists.txt index 170829fbc..ae13cd9f2 100644 --- a/sources/shiboken2/tests/libsample/CMakeLists.txt +++ b/sources/shiboken2/tests/libsample/CMakeLists.txt @@ -36,6 +36,7 @@ pointf.cpp polygon.cpp protected.cpp reference.cpp +renaming.cpp sample.cpp samplenamespace.cpp sbkdate.cpp diff --git a/sources/shiboken2/tests/libsample/modifications.cpp b/sources/shiboken2/tests/libsample/modifications.cpp index 56ba81875..627d17b45 100644 --- a/sources/shiboken2/tests/libsample/modifications.cpp +++ b/sources/shiboken2/tests/libsample/modifications.cpp @@ -165,3 +165,22 @@ Modifications::TestEnum Modifications::defaultEnumValue() const return TestEnumValue2; } +bool Modifications::wasGetAttroCalled() const +{ + return m_getAttroCalled; +} + +void Modifications::notifyGetAttroCalled() +{ + m_getAttroCalled = true; +} + +bool Modifications::wasSetAttroCalled() const +{ + return m_setAttroCalled; +} + +void Modifications::notifySetAttroCalled() +{ + m_setAttroCalled = true; +} diff --git a/sources/shiboken2/tests/libsample/modifications.h b/sources/shiboken2/tests/libsample/modifications.h index 674a05f27..888c66d18 100644 --- a/sources/shiboken2/tests/libsample/modifications.h +++ b/sources/shiboken2/tests/libsample/modifications.h @@ -132,9 +132,17 @@ public: TestEnum enumValue() const; TestEnum defaultEnumValue() const; + bool wasGetAttroCalled() const; + void notifyGetAttroCalled(); + + bool wasSetAttroCalled() const; + void notifySetAttroCalled(); + private: ObjectType* m_object; TestEnum m_enumValue = TestEnumValue1; + bool m_getAttroCalled = false; + bool m_setAttroCalled = false; }; class LIBSAMPLE_API AbstractModifications : public Modifications diff --git a/sources/shiboken2/tests/libsample/renaming.cpp b/sources/shiboken2/tests/libsample/renaming.cpp new file mode 100644 index 000000000..30586e1db --- /dev/null +++ b/sources/shiboken2/tests/libsample/renaming.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "renaming.h" + +#include <iostream> + +int ToBeRenamedValue::value() const +{ + return m_value; +} + +void ToBeRenamedValue::setValue(int v) +{ + m_value = v; +} + +void RenamedUser::useRenamedValue(const ToBeRenamedValue &v) +{ + std::cout << __FUNCTION__ << ' ' << v.value() << '\n'; +} diff --git a/sources/shiboken2/tests/libsample/renaming.h b/sources/shiboken2/tests/libsample/renaming.h new file mode 100644 index 000000000..cd88b36bf --- /dev/null +++ b/sources/shiboken2/tests/libsample/renaming.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RENAMING_H +#define RENAMING_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API ToBeRenamedValue +{ +public: + int value() const; + void setValue(int v); + +private: + int m_value = 42; +}; + +class LIBSAMPLE_API RenamedUser +{ +public: + void useRenamedValue(const ToBeRenamedValue &v); +}; + +#endif // POINT_H diff --git a/sources/shiboken2/tests/libsample/samplenamespace.h b/sources/shiboken2/tests/libsample/samplenamespace.h index 6868b5f0a..9e46b2ad6 100644 --- a/sources/shiboken2/tests/libsample/samplenamespace.h +++ b/sources/shiboken2/tests/libsample/samplenamespace.h @@ -51,6 +51,13 @@ enum EnumOnNamespace { Option3 = 3 }; +struct ObjectOnInvisibleNamespace +{ + bool exists() const { return true; } + static int toInt(EnumOnNamespace e) { return static_cast<int>(e); } + static ObjectOnInvisibleNamespace consume(const ObjectOnInvisibleNamespace &other) { return other; } +}; + }; namespace SampleNamespace @@ -137,6 +144,8 @@ protected: PublicScopedEnum protectedMethodReturningPublicScopedEnum() const; }; +LIBSAMPLE_API inline int enumAsInt(SomeClass::PublicScopedEnum value) { return static_cast<int>(value); } + class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough { public: diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp index 6a4deb50a..81fa30c7e 100644 --- a/sources/shiboken2/tests/libsmart/smart.cpp +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -93,7 +93,7 @@ Obj::~Obj() void Obj::printObj() { if (shouldPrint()) { std::cout << "integer value: " << m_integer - << " internal integer value: " << m_internalInteger->m_int << '\n'; + << " internal integer value: " << m_internalInteger->value() << '\n'; } } @@ -134,6 +134,17 @@ int Obj::takeSharedPtrToObj(SharedPtr<Obj> pObj) int Obj::takeSharedPtrToInteger(SharedPtr<Integer> pInt) { pInt->printInteger(); + return pInt->value(); +} + +SharedPtr<const Integer> Obj::giveSharedPtrToConstInteger() +{ + SharedPtr<const Integer> co(new Integer); + return co; +} + +int Obj::takeSharedPtrToConstInteger(SharedPtr<const Integer> pInt) +{ return pInt->m_int; } @@ -173,7 +184,17 @@ Integer::~Integer() std::cout << "Integer destructor " << this << '\n'; } -void Integer::printInteger() +int Integer::value() const +{ + return m_int; +} + +void Integer::setValue(int v) +{ + m_int = v; +} + +void Integer::printInteger() const { if (shouldPrint()) std::cout << "Integer value for object " << this << " is " << m_int << '\n'; diff --git a/sources/shiboken2/tests/libsmart/smart_integer.h b/sources/shiboken2/tests/libsmart/smart_integer.h index 3756f68b0..126894120 100644 --- a/sources/shiboken2/tests/libsmart/smart_integer.h +++ b/sources/shiboken2/tests/libsmart/smart_integer.h @@ -37,8 +37,12 @@ public: Integer(const Integer &other); Integer &operator=(const Integer &other); ~Integer(); - void printInteger(); - int m_int; + void printInteger() const; + + int value() const; + void setValue(int v); + + int m_int; // public for testing member field access. }; namespace Smart { diff --git a/sources/shiboken2/tests/libsmart/smart_obj.h b/sources/shiboken2/tests/libsmart/smart_obj.h index 12425366e..8fe45993f 100644 --- a/sources/shiboken2/tests/libsmart/smart_obj.h +++ b/sources/shiboken2/tests/libsmart/smart_obj.h @@ -48,12 +48,14 @@ public: Integer takeInteger(Integer val); SharedPtr<Obj> giveSharedPtrToObj(); std::vector<SharedPtr<Obj> > giveSharedPtrToObjList(int size); - SharedPtr<Integer> giveSharedPtrToInteger(); + virtual SharedPtr<Integer> giveSharedPtrToInteger(); // virtual for PYSIDE-1188 + SharedPtr<const Integer> giveSharedPtrToConstInteger(); + int takeSharedPtrToConstInteger(SharedPtr<const Integer> pInt); SharedPtr<Smart::Integer2> giveSharedPtrToInteger2(); int takeSharedPtrToObj(SharedPtr<Obj> pObj); int takeSharedPtrToInteger(SharedPtr<Integer> pInt); - int m_integer; + int m_integer; // public for testing member field access. Integer *m_internalInteger; }; diff --git a/sources/shiboken2/tests/otherbinding/CMakeLists.txt b/sources/shiboken2/tests/otherbinding/CMakeLists.txt index bc5c4bdad..05a282838 100644 --- a/sources/shiboken2/tests/otherbinding/CMakeLists.txt +++ b/sources/shiboken2/tests/otherbinding/CMakeLists.txt @@ -10,6 +10,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/other/number_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/otherderived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/othermultiplederived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/otherobjecttype_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/sharedptr_str_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/smartptrtester_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/other/other_module_wrapper.cpp ) @@ -28,8 +30,9 @@ COMMENT "Running generator for 'other' test binding..." add_library(other MODULE ${other_SRC}) target_include_directories(other PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${sample_BINARY_DIR}/sample) -target_link_libraries(other PUBLIC libother libsample libshiboken) + ${sample_BINARY_DIR}/sample + ${smart_BINARY_DIR}/smart) +target_link_libraries(other PUBLIC libother libsample libsmart libshiboken) set_property(TARGET other PROPERTY PREFIX "") set_property(TARGET other PROPERTY OUTPUT_NAME "other${PYTHON_EXTENSION_SUFFIX}") @@ -38,6 +41,6 @@ if(WIN32) endif() -add_dependencies(other sample) +add_dependencies(other sample smart) create_generator_target(other) diff --git a/sources/shiboken2/tests/otherbinding/global.h b/sources/shiboken2/tests/otherbinding/global.h index 0fccabb92..763566ae0 100644 --- a/sources/shiboken2/tests/otherbinding/global.h +++ b/sources/shiboken2/tests/otherbinding/global.h @@ -32,4 +32,5 @@ #include "otherderived.h" #include "otherobjecttype.h" #include "othermultiplederived.h" +#include "smartptrtester.h" diff --git a/sources/shiboken2/tests/otherbinding/other-binding.txt.in b/sources/shiboken2/tests/otherbinding/other-binding.txt.in index a17b70fc1..dbe935a9f 100644 --- a/sources/shiboken2/tests/otherbinding/other-binding.txt.in +++ b/sources/shiboken2/tests/otherbinding/other-binding.txt.in @@ -8,11 +8,13 @@ typesystem-file = @other_TYPESYSTEM@ output-directory = @CMAKE_CURRENT_BINARY_DIR@ include-path = @libother_SOURCE_DIR@ +include-path = @libsmart_SOURCE_DIR@ include-path = @libsample_SOURCE_DIR@ include-path = @libsample_SOURCE_DIR@/.. typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ typesystem-path = @sample_SOURCE_DIR@ +typesystem-path = @smart_SOURCE_DIR@ enable-parent-ctor-heuristic diff --git a/sources/shiboken2/tests/otherbinding/signature_test.py b/sources/shiboken2/tests/otherbinding/signature_test.py new file mode 100644 index 000000000..f3b712d04 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/signature_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for functions signature''' + +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from other import OtherObjectType +from shiboken_test_helper import objectFullname + +class SignatureTest(unittest.TestCase): + + # Check if the argument of 'OtherObjectType::enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value)' + # has the correct representation + def testNamespaceFromOtherModule(self): + argType = OtherObjectType.enumAsInt.__signature__.parameters['value'].annotation + self.assertEqual(objectFullname(argType), 'sample.SampleNamespace.SomeClass.PublicScopedEnum') + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/smartptr_test.py b/sources/shiboken2/tests/otherbinding/smartptr_test.py new file mode 100644 index 000000000..04f657757 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/smartptr_test.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for the SmartPtrTester class''' + +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from smart import Integer +from sample import Str +from other import SmartPtrTester + + +class SmartPtrTest(unittest.TestCase): + '''Test case for the SmartPtrTester class''' + + def test(self): + tester = SmartPtrTester() + + integerPtr = tester.createSharedPtrInteger(42) + self.assertEqual(tester.valueOfSharedPtrInteger(integerPtr), 42) + + strPtr = tester.createSharedPtrStr('hello') + self.assertEqual(tester.valueOfSharedPtrStr(strPtr), 'hello') + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/typesystem_other.xml b/sources/shiboken2/tests/otherbinding/typesystem_other.xml index 2932dafb3..78c4dd016 100644 --- a/sources/shiboken2/tests/otherbinding/typesystem_other.xml +++ b/sources/shiboken2/tests/otherbinding/typesystem_other.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <typesystem package="other"> <load-typesystem name="typesystem_sample.xml" generate="no" /> + <load-typesystem name="typesystem_smart.xml" generate="no" /> <object-type name="OtherObjectType" /> <object-type name="OtherDerived" /> @@ -9,6 +10,10 @@ <value-type name="ExtendsNoImplicitConversion" /> <value-type name="Number" /> + <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" + instantiations="Str"/> + <value-type name="SmartPtrTester"/> + <suppress-warning text="signature 'operator!=(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> <suppress-warning text="signature 'operator+(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> <suppress-warning text="signature 'operator==(ByteArray,const char*)' for function modification in 'ByteArray' not found." /> diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt index 61090d30e..b65068dc3 100644 --- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -94,6 +94,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/rect_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/rectf_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/reference_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/referentmodelindex_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/toberenamedvalue_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/renameduser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_sample_wrapper.cpp @@ -123,6 +125,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/filter_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/data_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/intersection_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/union_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/invisible_objectoninvisiblenamespace_wrapper.cpp ) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sample-binding.txt.in" diff --git a/sources/shiboken2/tests/samplebinding/global.h b/sources/shiboken2/tests/samplebinding/global.h index 3984102a8..f4e20b74f 100644 --- a/sources/shiboken2/tests/samplebinding/global.h +++ b/sources/shiboken2/tests/samplebinding/global.h @@ -75,6 +75,7 @@ #include "protected.h" #include "rect.h" #include "reference.h" +#include "renaming.h" #include "removednamespaces.h" #include "sample.h" #include "samplenamespace.h" diff --git a/sources/shiboken2/tests/samplebinding/modifications_test.py b/sources/shiboken2/tests/samplebinding/modifications_test.py index e6e9c5626..763ba04e5 100644 --- a/sources/shiboken2/tests/samplebinding/modifications_test.py +++ b/sources/shiboken2/tests/samplebinding/modifications_test.py @@ -235,6 +235,14 @@ class ModificationsTest(unittest.TestCase): modifications.setEnumValue() self.assertEqual(modifications.enumValue(), Modifications.TestEnumValue2) + def testSetGetAttro(self): + modifications = Modifications() + self.assertFalse(modifications.wasSetAttroCalled()) + setattr(modifications, 'Foo', 'Bar') + self.assertTrue(modifications.wasSetAttroCalled()) + self.assertEqual(getattr(modifications, 'Foo'), 'Bar') + self.assertTrue(modifications.wasGetAttroCalled()) + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/namespace_test.py b/sources/shiboken2/tests/samplebinding/namespace_test.py index aeaf81cff..23480d4c4 100644 --- a/sources/shiboken2/tests/samplebinding/namespace_test.py +++ b/sources/shiboken2/tests/samplebinding/namespace_test.py @@ -40,12 +40,17 @@ from shiboken_paths import init_paths init_paths() from sample import * +from shiboken_test_helper import objectFullname class TestEnumUnderNamespace(unittest.TestCase): def testInvisibleNamespace(self): o1 = EnumOnNamespace.Option1 self.assertEqual(o1, 1) + def testTpNames(self): + self.assertEqual(objectFullname(EnumOnNamespace), "sample.EnumOnNamespace") + self.assertEqual(str(EnumOnNamespace.Option1), + "sample.EnumOnNamespace.Option1") class TestClassesUnderNamespace(unittest.TestCase): def testIt(self): @@ -72,5 +77,19 @@ class TestClassesUnderNamespace(unittest.TestCase): self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>") + # Test if enum inside of class is correct represented + self.assertEqual(objectFullname(SampleNamespace.enumInEnumOut.__signature__.parameters['in_'].annotation), + "sample.SampleNamespace.InValue") + self.assertEqual(objectFullname(SampleNamespace.enumAsInt.__signature__.parameters['value'].annotation), + "sample.SampleNamespace.SomeClass.PublicScopedEnum") + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.toInt.__signature__.parameters['e'].annotation), + "sample.EnumOnNamespace") + + # Test if enum on namespace that was marked as not gerenated does not appear on type name + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace), + "sample.ObjectOnInvisibleNamespace") + self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.consume.__signature__.parameters['other'].annotation), + "sample.ObjectOnInvisibleNamespace") + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/renaming_test.py b/sources/shiboken2/tests/samplebinding/renaming_test.py new file mode 100644 index 000000000..cb59dce3a --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/renaming_test.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for renaming using target-lang-name attribute.''' + +import os +import re +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from shiboken_paths import init_paths +init_paths() + +from sample import RenamedValue, RenamedUser + +class RenamingTest(unittest.TestCase): + def test(self): + '''Tests whether the C++ class ToBeRenamedValue renamed via attribute + target-lang-name to RenamedValue shows up in consuming function + signature strings correctly. + ''' + renamed_value = RenamedValue() + self.assertEqual(str(type(renamed_value)), + "<class 'sample.RenamedValue'>") + rename_user = RenamedUser() + rename_user.useRenamedValue(renamed_value) + actual_signature = str(rename_user.useRenamedValue.__signature__) + self.assertTrue(re.match(r"^\(self,\s*v:\s*sample.RenamedValue\)$", + actual_signature)) + + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 3aaecf247..3cd318ceb 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -543,8 +543,9 @@ <enum-type identified-by-value="AnonymousGlobalEnum_Value0"/> - <namespace-type name="Invisible" generate="no"> + <namespace-type name="Invisible" visible="no"> <enum-type name="EnumOnNamespace" /> + <value-type name="ObjectOnInvisibleNamespace" /> </namespace-type> <namespace-type name="SampleNamespace"> @@ -1292,6 +1293,16 @@ <replace-default-expression with="cppSelf->defaultEnumValue()"/> </modify-argument> </modify-function> + <add-function signature="__getattro__" return-type="PyObject *"> + <inject-code class="target" position="beginning"> + cppSelf->notifyGetAttroCalled(); + </inject-code> + </add-function> + <add-function signature="__setattro__" return-type="int"> + <inject-code class="target" position="beginning"> + cppSelf->notifySetAttroCalled(); + </inject-code> + </add-function> </object-type> <object-type name="AbstractModifications"> @@ -2433,6 +2444,9 @@ <modify-function signature="dummy(std::list<std::pair<BlackBox *, BlackBox *> > &)" rename="dummy_method" /> </object-type> + <value-type name="ToBeRenamedValue" target-lang-name="RenamedValue"/> + <value-type name="RenamedUser"/> + <suppress-warning text="horribly broken type '__off64_t'" /> <suppress-warning text="enum '__codecvt_result' does not have a type entry or is not an enum" /> <suppress-warning text="Pure virtual method "Abstract::hideFunction(HideType*)" must be implement but was completely removed on typesystem." /> diff --git a/sources/shiboken2/tests/shiboken_test_helper.py b/sources/shiboken2/tests/shiboken_test_helper.py new file mode 100644 index 000000000..793baf4ad --- /dev/null +++ b/sources/shiboken2/tests/shiboken_test_helper.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + + +def objectFullname(t): + # '__qualname__' for Python 2 does exist for PySide types, only. + name = getattr(t, "__qualname__", t.__name__) + module = t.__module__ + if module is None or module == str.__class__.__module__: + return name + else: + return module + '.' + name diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py index 6210916d3..50b2120a2 100644 --- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py @@ -128,6 +128,10 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(integer.m_int, 50) # Set and get a member value via shared pointer (like operator->). + ptrToInteger.setValue(150) + self.assertEqual(ptrToInteger.value(), 150) + + # Set and get a member field via shared pointer (like operator->). ptrToInteger.m_int = 100 self.assertEqual(ptrToInteger.m_int, 100) @@ -155,6 +159,18 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(objCount(), 0) self.assertEqual(integerCount(), 0) + def testConstIntegerSmartPointer(self): + # Uncomment to see more debug info about creation of objects and ref counts. + # Registry.getInstance().setShouldPrint(True) + + # Create Obj. + o = Obj() + ptrToConstInteger = o.giveSharedPtrToConstInteger() + self.assertEqual(ptrToConstInteger.m_int, 456) + result = o.takeSharedPtrToConstInteger(ptrToConstInteger) + self.assertEqual(result, 456) + self.assertEqual(ptrToConstInteger.value(), 456) + def testSmartPointersWithNamespace(self): # Create the main object o = Obj() diff --git a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml index 0bb485957..8fb3082a0 100644 --- a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml +++ b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml @@ -43,7 +43,8 @@ possible to explicitly instantiate a new shared pointer in python e.g. o = SharedPtr_Foo() won't work. --> - <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" /> + <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" + instantiations="Integer,Smart::Integer2,Obj"/> <object-type name="Obj" /> <value-type name="Integer" /> diff --git a/sources/shiboken2/tests/test_generator/CMakeLists.txt b/sources/shiboken2/tests/test_generator/CMakeLists.txt index 5f5099897..07611e32c 100644 --- a/sources/shiboken2/tests/test_generator/CMakeLists.txt +++ b/sources/shiboken2/tests/test_generator/CMakeLists.txt @@ -1,3 +1,4 @@ +cmake_minimum_required(VERSION 3.1) project(test_generator) set(dummy_generator_SRC dummygenerator.cpp) @@ -8,7 +9,7 @@ set_property(TARGET dummy_generator PROPERTY PREFIX "") add_executable(dummygenerator main.cpp) set(DUMMYGENERATOR_EXECUTABLE dummygenerator${generator_SUFFIX}) set_target_properties(dummygenerator PROPERTIES OUTPUT_NAME ${DUMMYGENERATOR_EXECUTABLE}) -target_link_libraries(dummygenerator ${Qt5Core_LIBRARIES}) +target_link_libraries(dummygenerator ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES}) configure_file(dummygentestconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/dummygentestconfig.h" @ONLY) @@ -32,15 +33,8 @@ if(WIN32) endif() macro(m_add_test testname) - if(CMAKE_VERSION VERSION_LESS 2.8) - add_test(${testname} ${CMAKE_COMMAND} -DTEST=${testname} - -DWORKDIR=${CMAKE_CURRENT_BINARY_DIR} - -DENV_PATH=${ENV_PATH} -DENV_QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH} - -P ${CMAKE_CURRENT_SOURCE_DIR}/run_test.cmake) - else() - add_test(${testname} ${testname}) - set_property(TEST ${testname} PROPERTY ENVIRONMENT "PATH=${ENV_PATH}" "QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH}") - endif() + add_test(${testname} ${testname}) + set_property(TEST ${testname} PROPERTY ENVIRONMENT "PATH=${ENV_PATH}" "QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH}") endmacro() macro(declare_test testname) @@ -50,8 +44,8 @@ macro(declare_test testname) target_link_libraries(${testname} ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} - ${Qt5Test_LIBRARIES} - ${Qt5Core_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Test_LIBRARIES} + ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES} ) m_add_test(${testname}) endmacro(declare_test testname) diff --git a/tools/dump_metaobject.py b/tools/dump_metaobject.py new file mode 100644 index 000000000..873d90e65 --- /dev/null +++ b/tools/dump_metaobject.py @@ -0,0 +1,155 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt for Python project. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""Helper functions for formatting information on QMetaObject""" + +from PySide2.QtCore import (QMetaClassInfo, QMetaEnum, QMetaMethod, + QMetaProperty, QMetaObject, QObject) + + +def _qbytearray_to_string(b): + return bytes(b.data()).decode('utf-8') + + +def _dump_metaobject_helper(meta_obj, indent): + print('{}class {}:'.format(indent, meta_obj.className())) + indent += ' ' + + info_offset = meta_obj.classInfoOffset() + info_count = meta_obj.classInfoCount() + if info_offset < info_count: + print('{}Info:'.format(indent)) + for i in range(info_offset, info_count): + name = meta_obj.classInfo(i).name() + value = meta_obj.classInfo(i).value() + print('{}{:4d} {}+{}'.format(indent, i, name, value)) + + enumerator_offset = meta_obj.enumeratorOffset() + enumerator_count = meta_obj.enumeratorCount() + if enumerator_offset < enumerator_count: + print('{}Enumerators:'.format(indent)) + for e in range(enumerator_offset, enumerator_count): + meta_enum = meta_obj.enumerator(e) + name = meta_enum.name() + value_str = '' + descr = '' + if meta_enum.isFlag(): + descr += ' flag' + if meta_enum.isScoped(): + descr += ' scoped' + for k in range(0, meta_enum.keyCount()): + if k > 0: + value_str += ', ' + value_str += '{} = {}'.format(meta_enum.key(k), + meta_enum.value(k)) + print('{}{:4d} {}{} ({})'.format(indent, e, name, descr, + value_str)) + + property_offset = meta_obj.propertyOffset() + property_count = meta_obj.propertyCount() + if property_offset < property_count: + print('{}Properties:'.format(indent)) + for p in range(property_offset, property_count): + meta_property = meta_obj.property(p) + name = meta_property.name() + desc = '' + if meta_property.isConstant(): + desc += ', constant' + if meta_property.isDesignable: + desc += ', designable' + if meta_property.isFlagType: + desc += ', flag' + if meta_property.isEnumType(): + desc += ', enum' + if meta_property.isStored(): + desc += ', stored' + if meta_property.isWritable(): + desc += ', writable' + if meta_property.isResettable: + desc += ', resettable' + if meta_property.hasNotifySignal(): + notify_name = meta_property.notifySignal().name() + desc += ', notify={}'.format(_qbytearray_to_string(notify_name)) + print('{}{:4d} {} {}{}'.format(indent, p, meta_property.typeName(), + name, desc)) + + method_offset = meta_obj.methodOffset() + method_count = meta_obj.methodCount() + if method_offset < method_count: + print('{}Methods:'.format(indent)) + for m in range(method_offset, method_count): + method = meta_obj.method(m) + signature = _qbytearray_to_string(method.methodSignature()) + access = '' + if method.access() == QMetaMethod.Protected: + access += 'protected ' + elif method.access() == QMetaMethod.Private: + access += 'private ' + type = method.methodType() + typeString = '' + if type == QMetaMethod.Signal: + typeString = ' (Signal)' + elif type == QMetaMethod.Slot: + typeString = ' (Slot)' + elif type == QMetaMethod.Constructor: + typeString = ' (Ct)' + desc = '{}{:4d} {}{} {}{}'.format(indent, m, access, + method.typeName(), signature, + typeString) + parameter_names = method.parameterNames() + if parameter_names: + parameter_types = method.parameterTypes() + desc += ' Parameters:' + for p, bname in enumerate(parameter_names): + name = _qbytearray_to_string(bname) + type = _qbytearray_to_string(parameter_types[p]) + desc += ' {}: {}'.format(name if name else '<unnamed>', type) + print(desc) + + +def dump_metaobject(meta_obj): + super_classes = [meta_obj] + super_class = meta_obj.superClass() + while super_class: + super_classes.append(super_class) + super_class = super_class.superClass() + indent = '' + for c in reversed(super_classes): + _dump_metaobject_helper(c, indent) + indent += ' ' diff --git a/tools/metaobject_dump.py b/tools/metaobject_dump.py new file mode 100644 index 000000000..6c7a9f7df --- /dev/null +++ b/tools/metaobject_dump.py @@ -0,0 +1,67 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt for Python project. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import sys +from dump_metaobject import dump_metaobject + +# Import all widget classes to enable instantiating them by type name +from PySide2.QtWidgets import * + + +DESC = """ +metaobject_dump.py <class_name> + +Dumps the QMetaObject of a class + +Example: metaobject_dump QLabel +""" + + +if __name__ == '__main__': + if len(sys.argv) != 2: + print(DESC) + sys.exit(0) + app = QApplication(sys.argv) + + type_name = sys.argv[1] + type_instance = eval(type_name) + if not type_instance: + print('Invalid type {}'.format(type_name)) + sys.exit(1) + dump_metaobject(type_instance.staticMetaObject) diff --git a/tools/metaobject_dump.pyproject b/tools/metaobject_dump.pyproject new file mode 100644 index 000000000..f6d85b571 --- /dev/null +++ b/tools/metaobject_dump.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["metaobject_dump.py", "dump_metaobject.py"] +} diff --git a/tools/missing_bindings-requirements.txt b/tools/missing_bindings-requirements.txt new file mode 100644 index 000000000..4ddb60aa8 --- /dev/null +++ b/tools/missing_bindings-requirements.txt @@ -0,0 +1,7 @@ +pyside2 +pyqt5 +beautifulsoup4 +pyqt3d +pyqtchart +pyqtdatavisualization +pyqtwebengine diff --git a/tools/missing_bindings.py b/tools/missing_bindings.py index a4a418a6e..33a296832 100644 --- a/tools/missing_bindings.py +++ b/tools/missing_bindings.py @@ -115,6 +115,7 @@ modules_to_test['QtPositioning'] = 'qtpositioning-module.html' modules_to_test['QtRemoteObjects'] = 'qtremoteobjects-module.html' modules_to_test['QtScriptTools'] = 'qtscripttools-module.html' modules_to_test['QtSensors'] = 'qtsensors-module.html' +modules_to_test['QtSerialPort'] = 'qtserialport-module.html' types_to_ignore = set() # QtCore types_to_ignore.add('QFlag') @@ -226,7 +227,8 @@ qt_documentation_website_prefixes['5.11'] = 'http://doc.qt.io/qt-5.11/' qt_documentation_website_prefixes['5.11'] = 'http://doc.qt.io/qt-5.11/' qt_documentation_website_prefixes['5.12'] = 'http://doc.qt.io/qt-5.12/' qt_documentation_website_prefixes['5.13'] = 'http://doc.qt.io/qt-5.13/' -qt_documentation_website_prefixes['5.14'] = 'http://doc.qt.io/qt-5/' +qt_documentation_website_prefixes['5.14'] = 'http://doc.qt.io/qt-5.14/' +qt_documentation_website_prefixes['5.15'] = 'http://doc.qt.io/qt-5/' qt_documentation_website_prefixes['dev'] = 'http://doc-snapshots.qt.io/qt5-dev/' @@ -249,8 +251,8 @@ parser.add_argument("module", help="the Qt module for which to get the missing types") parser.add_argument("--qt-version", "-v", - default='5.12', - choices=['5.6', '5.9', '5.11', '5.12', '5.13', '5.14', 'dev'], + default='5.15', + choices=['5.6', '5.9', '5.11', '5.12', '5.13', '5.14', '5.15', 'dev'], type=str, dest='version', help="the Qt version to use to check for types") |