diff options
39 files changed, 749 insertions, 242 deletions
diff --git a/examples/charts/callout.py b/examples/charts/callout.py new file mode 100644 index 000000000..0bc7cdaf5 --- /dev/null +++ b/examples/charts/callout.py @@ -0,0 +1,258 @@ +#!/usr/bin/python + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the PySide 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 Callout example from Qt v5.x""" + +import sys +from PySide2.QtWidgets import (QApplication, QWidget, QGraphicsScene, + QGraphicsView, QGraphicsSimpleTextItem, QGraphicsItem) +from PySide2.QtCore import Qt, QPointF, QRectF, QRect +from PySide2.QtCharts import QtCharts +from PySide2.QtGui import QPainter, QFont, QFontMetrics, QPainterPath, QColor + + +class Callout(QGraphicsItem): + + def __init__(self, chart): + QGraphicsItem.__init__(self, chart) + self._chart = chart + self._text = "" + self._textRect = QRectF() + self._anchor = QPointF() + self._font = QFont() + self._rect = QRectF() + + def boundingRect(self): + anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) + rect = QRectF() + rect.setLeft(min(self._rect.left(), anchor.x())) + rect.setRight(max(self._rect.right(), anchor.x())) + rect.setTop(min(self._rect.top(), anchor.y())) + rect.setBottom(max(self._rect.bottom(), anchor.y())) + + return rect + + def paint(self, painter, option, widget): + path = QPainterPath() + path.addRoundedRect(self._rect, 5, 5) + anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) + if not self._rect.contains(anchor): + point1 = QPointF() + point2 = QPointF() + + # establish the position of the anchor point in relation to _rect + above = anchor.y() <= self._rect.top() + aboveCenter = (anchor.y() > self._rect.top() and + anchor.y() <= self._rect.center().y()) + belowCenter = (anchor.y() > self._rect.center().y() and + anchor.y() <= self._rect.bottom()) + below = anchor.y() > self._rect.bottom() + + onLeft = anchor.x() <= self._rect.left() + leftOfCenter = (anchor.x() > self._rect.left() and + anchor.x() <= self._rect.center().x()) + rightOfCenter = (anchor.x() > self._rect.center().x() and + anchor.x() <= self._rect.right()) + onRight = anchor.x() > self._rect.right() + + # get the nearest _rect corner. + x = (onRight + rightOfCenter) * self._rect.width() + y = (below + belowCenter) * self._rect.height() + cornerCase = ((above and onLeft) or (above and onRight) or + (below and onLeft) or (below and onRight)) + vertical = abs(anchor.x() - x) > abs(anchor.y() - y) + + x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * + int(not vertical) * (onLeft * 10 - onRight * 20)) + y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase * + vertical * (above * 10 - below * 20)) + point1.setX(x1) + point1.setY(y1) + + x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * + int(not vertical) * (onLeft * 20 - onRight * 10)) + y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase * + vertical * (above * 20 - below * 10)) + point2.setX(x2) + point2.setY(y2) + + path.moveTo(point1) + path.lineTo(anchor) + path.lineTo(point2) + path = path.simplified() + + painter.setBrush(QColor(255, 255, 255)) + painter.drawPath(path) + painter.drawText(self._textRect, self._text) + + def mousePressEvent(self, event): + event.setAccepted(True) + + def mouseMoveEvent(self, event): + if event.buttons() & Qt.LeftButton: + self.setPos(mapToParent( + event.pos() - event.buttonDownPos(Qt.LeftButton))) + event.setAccepted(Ttrue) + else: + event.setAccepted(False) + + def setText(self, text): + self._text = text + metrics = QFontMetrics(self._font) + self._textRect = QRectF(metrics.boundingRect( + QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text)) + self._textRect.translate(5, 5) + self.prepareGeometryChange() + self._rect = self._textRect.adjusted(-5, -5, 5, 5) + + def setAnchor(self, point): + self._anchor = QPointF(point) + + def updateGeometry(self): + self.prepareGeometryChange() + self.setPos(self._chart.mapToPosition( + self._anchor) + QPointF(10, -50)) + + +class View(QGraphicsView): + def __init__(self, parent = None): + super(View, self).__init__(parent) + self.setScene(QGraphicsScene(self)) + + self.setDragMode(QGraphicsView.NoDrag) + self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + + # Chart + self._chart = QtCharts.QChart() + self._chart.setMinimumSize(640, 480) + self._chart.setTitle("Hover the line to show callout. Click the line " + "to make it stay") + self._chart.legend().hide() + self.series = QtCharts.QLineSeries() + self.series.append(1, 3) + self.series.append(4, 5) + self.series.append(5, 4.5) + self.series.append(7, 1) + self.series.append(11, 2) + self._chart.addSeries(self.series) + + self.series2 = QtCharts.QSplineSeries() + self.series2.append(1.6, 1.4) + self.series2.append(2.4, 3.5) + self.series2.append(3.7, 2.5) + self.series2.append(7, 4) + self.series2.append(10, 2) + self._chart.addSeries(self.series2) + + self._chart.createDefaultAxes() + self._chart.setAcceptHoverEvents(True) + + self.setRenderHint(QPainter.Antialiasing) + self.scene().addItem(self._chart) + + self._coordX = QGraphicsSimpleTextItem(self._chart) + self._coordX.setPos( + self._chart.size().width()/2 - 50, self._chart.size().height()) + self._coordX.setText("X: "); + self._coordY = QGraphicsSimpleTextItem(self._chart) + self._coordY.setPos( + self._chart.size().width()/2 + 50, self._chart.size().height()) + self._coordY.setText("Y: ") + + self._callouts = [] + self._tooltip = Callout(self._chart) + + self.series.clicked.connect(self.keepCallout) + self.series.hovered.connect(self.tooltip) + + self.series2.clicked.connect(self.keepCallout) + self.series2.hovered.connect(self.tooltip) + + self.setMouseTracking(True) + + def resizeEvent(self, event): + if self.scene(): + self.scene().setSceneRect(QRectF(QPointF(0, 0), event.size())) + self._chart.resize(event.size()) + self._coordX.setPos( + self._chart.size().width()/2 - 50, + self._chart.size().height() - 20) + self._coordY.setPos( + self._chart.size().width()/2 + 50, + self._chart.size().height() - 20) + for callout in self._callouts: + callout.updateGeometry() + QGraphicsView.resizeEvent(self, event) + + + def mouseMoveEvent(self, event): + self._coordX.setText("X: {0:.2f}" + .format(self._chart.mapToValue(event.pos()).x())) + self._coordY.setText("Y: {0:.2f}" + .format(self._chart.mapToValue(event.pos()).y())) + QGraphicsView.mouseMoveEvent(self, event) + + def keepCallout(self): + self._callouts.append(self._tooltip); + self._tooltip = Callout(self._chart) + + def tooltip(self, point, state): + if self._tooltip == 0: + self._tooltip = Callout(self._chart) + + if state: + self._tooltip.setText("X: {0:.2f} \nY: {1:.2f} " + .format(point.x(),point.y())) + self._tooltip.setAnchor(point) + self._tooltip.setZValue(11) + self._tooltip.updateGeometry() + self._tooltip.show() + else: + self._tooltip.hide() + + +if __name__ == "__main__": + app = QApplication(sys.argv) + v = View() + v.show() + sys.exit(app.exec_()) diff --git a/examples/charts/lineandbar.py b/examples/charts/lineandbar.py new file mode 100644 index 000000000..a9ae8b4d6 --- /dev/null +++ b/examples/charts/lineandbar.py @@ -0,0 +1,117 @@ +#!/usr/bin/python + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the PySide 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 line/bar example from Qt v5.x""" + +import sys +from PySide2.QtCore import QPoint, Qt +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.set0 = QtCharts.QBarSet("Jane") + self.set1 = QtCharts.QBarSet("John") + self.set2 = QtCharts.QBarSet("Axel") + self.set3 = QtCharts.QBarSet("Mary") + self.set4 = QtCharts.QBarSet("Sam") + + self.set0.append([1, 2, 3, 4, 5, 6]) + self.set1.append([5, 0, 0, 4, 0, 7]) + self.set2.append([3, 5, 8, 13, 8, 5]) + self.set3.append([5, 6, 7, 3, 4, 5]) + self.set4.append([9, 7, 5, 3, 1, 2]) + + self.barSeries = QtCharts.QBarSeries() + self.barSeries.append(self.set0) + self.barSeries.append(self.set1) + self.barSeries.append(self.set2) + self.barSeries.append(self.set3) + self.barSeries.append(self.set4) + + self.lineSeries = QtCharts.QLineSeries() + self.lineSeries.setName("trend") + self.lineSeries.append(QPoint(0, 4)) + self.lineSeries.append(QPoint(1, 15)) + self.lineSeries.append(QPoint(2, 20)) + self.lineSeries.append(QPoint(3, 4)) + self.lineSeries.append(QPoint(4, 12)) + self.lineSeries.append(QPoint(5, 17)) + + self.chart = QtCharts.QChart() + self.chart.addSeries(self.barSeries) + self.chart.addSeries(self.lineSeries) + self.chart.setTitle("Line and barchart example") + + self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] + self.axisX = QtCharts.QBarCategoryAxis() + self.axisX.append(self.categories) + self.chart.setAxisX(self.axisX, self.lineSeries) + self.chart.setAxisX(self.axisX, self.barSeries) + self.axisX.setRange("Jan", "Jun") + + self.axisY = QtCharts.QValueAxis() + self.chart.setAxisY(self.axisY, self.lineSeries) + self.chart.setAxisY(self.axisY, self.barSeries) + self.axisY.setRange(0, 20) + + self.chart.legend().setVisible(True) + self.chart.legend().setAlignment(Qt.AlignBottom) + + 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/scriptableapplication/CMakeLists.txt b/examples/scriptableapplication/CMakeLists.txt index 6641d77c6..368fd7d25 100644 --- a/examples/scriptableapplication/CMakeLists.txt +++ b/examples/scriptableapplication/CMakeLists.txt @@ -37,7 +37,7 @@ endmacro() # Get relevant general paths, include paths and linker flags. pyside2_config(--pyside2 PYSIDE2_PATH) -set(SHIBOKEN_PATH "${PYSIDE2_PATH}/shiboken2") +set(SHIBOKEN_PATH "${PYSIDE2_PATH}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}") if(NOT EXISTS ${SHIBOKEN_PATH}) message(FATAL_ERROR "Shiboken executable not found at path: ${SHIBOKEN_PATH}") diff --git a/examples/scriptableapplication/pyside2_config.py b/examples/scriptableapplication/pyside2_config.py index 361043aef..0eba6cc23 100644 --- a/examples/scriptableapplication/pyside2_config.py +++ b/examples/scriptableapplication/pyside2_config.py @@ -125,6 +125,9 @@ def pythonLinkCmake(): def pythonLinkData(): # @TODO Fix to work with static builds of Python libdir = sysconfig.get_config_var('LIBDIR') + if libdir is None: + libdir = os.path.abspath(os.path.join( + sysconfig.get_config_var('LIBDEST'), "..", "libs")) version = pythonVersion() version_no_dots = version.replace('.', '') @@ -40,96 +40,178 @@ from __future__ import print_function from distutils.version import LooseVersion -"""This is a distutils setup-script for the PySide2 project +""" +This is a distutils setup-script for the Qt for Python project To build PySide2 simply execute: - python setup.py build --qmake=</path/to/qt/bin/qmake> [--cmake=</path/to/cmake>] [only Windows --openssl=</path/to/openssl/bin>] + python setup.py build or - python setup.py install --qmake=</path/to/qt/bin/qmake> [--cmake=</path/to/cmake>] [only Windows --openssl=</path/to/openssl/bin>] + python setup.py install to build and install into your current Python installation. -On Linux and macOS you can use option --standalone, to embed Qt libraries into the PySide2 package. -The option does not affect Windows, because it is used implicitly, i.e. all relevant DLLs have to -be copied into the PySide2 package anyway, because there is no proper rpath support on the platform. - -You can use option --rpath="your_value" to specify what rpath values should be embedded into the -PySide2 modules and shared libraries. This overrides the automatically generated values when the -option is not specified. - -You can use option --only-package, if you want to create more binary packages (bdist_wheel, bdist_egg, ...) -without rebuilding entire PySide2 every time: - # First time we create bdist_wheel with full PySide2 build - python setup.py bdist_wheel --qmake=c:\Qt\5.6\bin\qmake.exe --cmake=c:\tools\cmake\bin\cmake.exe --openssl=c:\libs\OpenSSL32bit\bin - - # Then we create bdist_egg reusing PySide2 build with option --only-package - python setup.py bdist_egg --only-package --qmake=c:\Qt\5.6\bin\qmake.exe --cmake=c:\tools\cmake\bin\cmake.exe --opnessl=c:\libs\OpenSSL32bit\bin - -You can use the option --qt-conf-prefix to pass a path relative to the PySide2 installed package, -which will be embedded into an auto-generated qt.conf registered in the Qt resource system. This -path will serve as the PrefixPath for QLibraryInfo, thus allowing to choose where Qt plugins -should be loaded from. This option overrides the usual prefix chosen by --standalone option, or when -building on Windows. -To temporarily disable registration of the internal qt.conf file, a new environment variable called -PYSIDE_DISABLE_INTERNAL_QT_CONF is introduced. You should assign the integer "1" to disable the -internal qt.conf, or "0" (or leave empty) to keep use the internal qt.conf file. - -For development purposes the following options might be of use, when using "setup.py build": - --reuse-build option allows recompiling only the modified sources and not the whole world, - shortening development iteration time, - --skip-cmake will reuse the already generated Makefiles (or equivalents), instead of invoking, - CMake to update the Makefiles (note, CMake should be ran at least once to generate the files), - --skip-make-install will not run make install (or equivalent) for each built module, - --skip-packaging will skip creation of the python package, - --ignore-git will skip the fetching and checkout steps for supermodule and all submodules. - --verbose-build will output the compiler invocation with command line arguments, etc. - --sanitize-address will build all targets with address sanitizer enabled. + +Optionally, one can specify the location of qmake and cmake if it is +not on the current PATH with: + --qmake=/path/to/qt/bin/qmake +and + --cmake=/path/to/bin/cmake +respectively. + +For windows, if OpenSSL support is required, it is necessary to specify +the directory with: + --openssl=/path/to/openssl/bin + +ADDITIONAL OPTIONS: + +On Linux and macOS you can use the option `--standalone` to embed Qt +libraries into the PySide2 package. +The option does not affect Windows, because it is used implicitly, +i.e. all relevant DLLs have to be copied into the PySide2 package +anyway, because there is no proper rpath support on the platform. + +You can use the option `--rpath=/path/to/lib/path` to specify which +rpath values should be embedded into the PySide2 modules and shared +libraries. +This overrides the automatically generated values when the option is +not specified. + +You can use the option `--only-package` if you want to create more +binary packages (bdist_wheel, bdist_egg, ...) without rebuilding the +entire PySide2 every time: + +e.g.: + +* First, we create a bdist_wheel from a full PySide2 build: + + python setup.py bdist_wheel --qmake=c:\Qt\5.9\bin\qmake.exe + --cmake=c:\tools\cmake\bin\cmake.exe + --openssl=c:\libs\OpenSSL32bit\bin + +* Then, we create a bdist_egg reusing PySide2 build with option + `--only-package`: + + python setup.py bdist_egg --only-package + --qmake=c:\Qt\5.9\bin\qmake.exe + --cmake=c:\tools\cmake\bin\cmake.exe + --openssl=c:\libs\OpenSSL32bit\bin + +You can use the option `--qt-conf-prefix` to pass a path relative to +the PySide2 installed package, which will be embedded into an +auto-generated `qt.conf` registered in the Qt resource system. +This path will serve as the PrefixPath for QLibraryInfo, thus allowing +to choose where Qt plugins should be loaded from. +This option overrides the usual prefix chosen by `--standalone` option, +or when building on Windows. + +To temporarily disable registration of the internal `qt.conf` file, a +new environment variable called PYSIDE_DISABLE_INTERNAL_QT_CONF is +introduced. + +You should assign the integer "1" to disable the internal `qt.conf`, +or "0" (or leave empty) to keep usining the internal `qt.conf` file. + +DEVELOPMENT OPTIONS: + +For development purposes the following options might be of use, when +using `setup.py build`: + + --reuse-build option allows recompiling only the modified sources and + not the whole world, shortening development iteration time, + --skip-cmake will reuse the already generated Makefiles (or + equivalents), instead of invoking, CMake to update the + Makefiles (note, CMake should be ran at least once to generate + the files), + --skip-make-install will not run make install (or equivalent) for + each module built, + --skip-packaging will skip creation of the python package, + --ignore-git will skip the fetching and checkout steps for + supermodule and all submodules. + --verbose-build will output the compiler invocation with command line + arguments, etc. + --sanitize-address will build the project with address sanitizer + enabled (Linux or macOS only). REQUIREMENTS: -- Python: 2.6, 2.7, 3.3, 3.4, 3.5 and 3.6 are supported -- Cmake: Specify the path to cmake with --cmake option or add cmake to the system path. -- Qt: 5.5 and 5.6 are supported. Specify the path to qmake with --qmake option or add qmake to the system path. + +* Python: 2.7 and 3.3+ are supported +* CMake: Specify the path to cmake with `--cmake` option or add cmake + to the system path. +* Qt: 5.9 and 5.11 are supported. Specify the path to qmake with + `--qmake` option or add qmake to the system path. OPTIONAL: -OpenSSL: - Specifying the --openssl option is only required on Windows. It is a no-op for other platforms. - You can specify the location of OpenSSL DLLs with option --openssl=</path/to/openssl/bin>. - You can download OpenSSL for Windows here: http://slproweb.com/products/Win32OpenSSL.html - - Official Qt packages do not link to the SSL library directly, but rather try to find the library - at runtime. - - On Windows, official Qt builds will try to pick up OpenSSL libraries at application path, - system registry, or in the PATH environment variable. - On macOS, official Qt builds use SecureTransport (provided by OS) instead of OpenSSL. - On Linux, official Qt builds will try to pick up the system OpenSSL library. - - Note: this means that Qt packages that directly link to the OpenSSL shared libraries, are not - currently compatible with standalone PySide2 packages. - -OS X SDK: You can specify which OS X SDK should be used for compilation with the option --osx-sysroot=</path/to/sdk>. - For e.g. "--osx-sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/". - -OS X Minimum deployment target: - You can specify a custom OS X minimum deployment target with the --osx-deployment-target=<value> - option. - For example: "--osx-deployment-target=10.10". - - If the option is not set, the minimum deployment target of the used Qt library will be used - instead. Thus it is not necessary to use the option without a good reason. - If a new value is specified, it has to be higher or equal to both Python's and Qt's minimum - deployment targets. - - Description: - OS X allows specifying a minimum OS version on which a binary will be able to run. This implies - that an application can be built on a machine with the latest OS X version installed, with - latest Xcode version and SDK version and the built application can still run on an older OS - version. + +* OpenSSL: + Specifying the --openssl option is only required on Windows. + It is a no-op for other platforms. + + You can specify the location of OpenSSL DLLs with option: + --openssl=</path/to/openssl/bin>. + + You can download OpenSSL for Windows here: + http://slproweb.com/products/Win32OpenSSL.html (*) + + Official Qt packages do not link to the SSL library directly, but + rather try to find the library at runtime. + + On Windows, official Qt builds will try to pick up OpenSSL + libraries at application path, system registry, or in the PATH + environment variable. + + On macOS, official Qt builds use SecureTransport (provided by OS) + instead of OpenSSL. + + On Linux, official Qt builds will try to pick up the system OpenSSL + library. + + Note: this means that Qt packages that directly link to the OpenSSL + shared libraries, are not currently compatible with + standalone PySide2 packages. + + (*) Revised on 23.03.2018 + +* macOS SDK: + You can specify which macOS SDK should be used for compilation with + the option: + --osx-sysroot=</path/to/sdk>. + + e.g.: "--osx-sysroot=/Applications/.../Developer/SDKs/MacOSX10.11.sdk/" + +* macOS minimum deployment target: + You can specify a custom macOS minimum deployment target with the + option: + --osx-deployment-target=<value> + + e.g.: "--osx-deployment-target=10.10" + + If the option is not set, the minimum deployment target of the used + Qt library will be used instead. Thus it is not necessary to use + the option without a good reason. + + If a new value is specified, it has to be higher or equal to both + Python's and Qt's minimum deployment targets. + + Description: macOS allows specifying a minimum OS version on which + a binary will be able to run. This implies that an + application can be built on a machine with the latest + macOS version installed, with latest Xcode version and + SDK version and the built application can still run on + an older OS version. """ import os import time from utils import memoize, has_option, get_python_dict OPTION_SNAPSHOT_BUILD = has_option("snapshot-build") + +# Change the cwd to setup.py's dir. +try: + this_file = __file__ +except NameError: + this_file = sys.argv[0] +this_file = os.path.abspath(this_file) +if os.path.dirname(this_file): + os.chdir(os.path.dirname(this_file)) script_dir = os.getcwd() @memoize @@ -226,7 +308,7 @@ def check_allowed_python_version(): import re pattern = "'Programming Language :: Python :: (\d+)\.(\d+)'" supported = [] - with open(__file__) as setup: + with open(this_file) as setup: for line in setup.readlines(): found = re.search(pattern, line) if found: @@ -346,15 +428,6 @@ if OPTION_ICULIB: if not OPTION_STANDALONE: print("--iculib-url option is a no-op option and will be removed soon.") -# Change the cwd to our source dir -try: - this_file = __file__ -except NameError: - this_file = sys.argv[0] -this_file = os.path.abspath(this_file) -if os.path.dirname(this_file): - os.chdir(os.path.dirname(this_file)) - def is_debug_python(): return getattr(sys, "gettotalrefcount", None) is not None @@ -1569,6 +1642,8 @@ class pyside_build(_build): qt_artifacts_permanent = [ "opengl*.dll", "d3d*.dll", + "libEGL*.dll", + "libGLESv2*.dll", "designer.exe", "linguist.exe", "lrelease.exe", @@ -1633,8 +1708,9 @@ class pyside_build(_build): # <qt>/plugins/* -> <setup>/PySide2/plugins plugin_dll_patterns = ["*{}.dll"] + pdb_pattern = "*{}.pdb" if copy_pdbs: - plugin_dll_patterns += ["*{}.pdb"] + plugin_dll_patterns += [pdb_pattern] plugin_dll_filter = functools.partial(qt_build_config_filter, plugin_dll_patterns) copydir("{qt_plugins_dir}", "{pyside_package_dir}/PySide2/plugins", file_filter_function=plugin_dll_filter, @@ -1648,9 +1724,11 @@ class pyside_build(_build): # <qt>/qml/* -> <setup>/PySide2/qml qml_dll_patterns = ["*{}.dll"] + qml_ignore_patterns = qml_dll_patterns + [pdb_pattern] + # Remove the "{}" from the patterns + qml_ignore = [a.format('') for a in qml_ignore_patterns] if copy_pdbs: - qml_dll_patterns += ["*{}.pdb"] - qml_ignore = [a.format('') for a in qml_dll_patterns] + qml_dll_patterns += [pdb_pattern] qml_dll_filter = functools.partial(qt_build_config_filter, qml_dll_patterns) copydir("{qt_qml_dir}", "{pyside_package_dir}/PySide2/qml", ignore=qml_ignore, diff --git a/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml b/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml index ca7646421..5932365a7 100644 --- a/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml +++ b/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml @@ -72,7 +72,7 @@ <object-type name="QChart" since="5.7"> <enum-type name="ChartType"/> <enum-type name="ChartTheme"/> - <enum-type name="AnimationOption"/> + <enum-type name="AnimationOption" flags="AnimationOptions"/> <modify-function signature="addSeries(QAbstractSeries*)"> <modify-argument index="1"> <parent index="this" action="add"/> diff --git a/sources/pyside2/PySide2/QtCore/CMakeLists.txt b/sources/pyside2/PySide2/QtCore/CMakeLists.txt index f2770f802..5a8a41ec5 100644 --- a/sources/pyside2/PySide2/QtCore/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtCore/CMakeLists.txt @@ -121,6 +121,7 @@ ${QtCore_GEN_DIR}/qstatemachine_signalevent_wrapper.cpp ${QtCore_GEN_DIR}/qstatemachine_wrappedevent_wrapper.cpp ${QtCore_GEN_DIR}/qstatemachine_wrapper.cpp ${QtCore_GEN_DIR}/qstorageinfo_wrapper.cpp +${QtCore_GEN_DIR}/qstringlistmodel_wrapper.cpp ${QtCore_GEN_DIR}/qsysinfo_wrapper.cpp ${QtCore_GEN_DIR}/qsystemsemaphore_wrapper.cpp ${QtCore_GEN_DIR}/qt_wrapper.cpp diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 2b838945d..360cc3983 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -4226,6 +4226,7 @@ s1.addTransition(button.clicked, s1h)</code> <object-type name="QRunnable"/> <object-type name="QPluginLoader"/> + <object-type name="QStringListModel"/> <suppress-warning text="Unable to decide type of property: 'QLibrary::LoadHints' in class 'QPluginLoader'" /> <suppress-warning text="enum '_ISalnum' does not have a type entry or is not an enum" /> diff --git a/sources/pyside2/PySide2/QtGui/CMakeLists.txt b/sources/pyside2/PySide2/QtGui/CMakeLists.txt index 784280ca6..807f9b31e 100644 --- a/sources/pyside2/PySide2/QtGui/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtGui/CMakeLists.txt @@ -121,7 +121,6 @@ ${QtGui_GEN_DIR}/qshowevent_wrapper.cpp ${QtGui_GEN_DIR}/qstandarditem_wrapper.cpp ${QtGui_GEN_DIR}/qstandarditemmodel_wrapper.cpp ${QtGui_GEN_DIR}/qstatustipevent_wrapper.cpp -${QtGui_GEN_DIR}/qstringlistmodel_wrapper.cpp ${QtGui_GEN_DIR}/qopenglbuffer_wrapper.cpp ${QtGui_GEN_DIR}/qopenglcontext_wrapper.cpp ${QtGui_GEN_DIR}/qaccessible_wrapper.cpp diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index 0f6d48968..0c43fde1f 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -1655,7 +1655,6 @@ <!-- ??? --> <modify-function signature="operator<(QStandardItem)const" remove="all"/> </object-type> - <object-type name="QStringListModel"/> <object-type name="QSyntaxHighlighter"> <modify-function signature="setCurrentBlockUserData(QTextBlockUserData*)"> <modify-argument index="1"> @@ -1762,7 +1761,7 @@ <object-type name="QDropEvent" polymorphic-id-expression="%1->type() == QEvent::Drop"> <modify-function signature="source() const"> <modify-argument index="return"> - <define-ownership owner="target"/> + <define-ownership class="target" owner="default" /> </modify-argument> </modify-function> </object-type> diff --git a/sources/pyside2/doc/inheritance_diagram.py b/sources/pyside2/doc/inheritance_diagram.py index 038c22f29..054cb7be9 100644 --- a/sources/pyside2/doc/inheritance_diagram.py +++ b/sources/pyside2/doc/inheritance_diagram.py @@ -47,10 +47,9 @@ except ImportError: from md5 import md5 from docutils import nodes -from docutils.parsers.rst import directives +from docutils.parsers.rst import directives, Directive from sphinx.ext.graphviz import render_dot_html, render_dot_latex -from sphinx.util.compat import Directive class InheritanceException(Exception): pass diff --git a/sources/pyside2/tests/QtGui/CMakeLists.txt b/sources/pyside2/tests/QtGui/CMakeLists.txt index eeb7c7e36..b487a2401 100644 --- a/sources/pyside2/tests/QtGui/CMakeLists.txt +++ b/sources/pyside2/tests/QtGui/CMakeLists.txt @@ -3,7 +3,6 @@ PYSIDE_TEST(bug_300_test.py) PYSIDE_TEST(bug_367.py) PYSIDE_TEST(bug_480.py) -PYSIDE_TEST(bug_500.py) PYSIDE_TEST(bug_606.py) PYSIDE_TEST(bug_617.py) PYSIDE_TEST(bug_652.py) diff --git a/sources/pyside2/tests/QtGui/bug_300_test.py b/sources/pyside2/tests/QtGui/bug_300_test.py index 1ab71569a..e8adca014 100644 --- a/sources/pyside2/tests/QtGui/bug_300_test.py +++ b/sources/pyside2/tests/QtGui/bug_300_test.py @@ -26,8 +26,7 @@ ## ############################################################################# -from PySide2.QtGui import QStringListModel -from PySide2.QtCore import QModelIndex +from PySide2.QtCore import QModelIndex, QStringListModel import unittest class TestQAbstractItemModelSignals(unittest.TestCase): diff --git a/sources/pyside2/tests/QtGui/bug_716.py b/sources/pyside2/tests/QtGui/bug_716.py index 49a329bc2..8bf07d6e2 100644 --- a/sources/pyside2/tests/QtGui/bug_716.py +++ b/sources/pyside2/tests/QtGui/bug_716.py @@ -26,8 +26,7 @@ ## ############################################################################# -from PySide2.QtCore import Qt, QPersistentModelIndex -from PySide2.QtGui import QStringListModel +from PySide2.QtCore import Qt, QPersistentModelIndex, QStringListModel if __name__ == '__main__': stringListModel = QStringListModel(['one', 'two']) diff --git a/sources/pyside2/tests/QtPrintSupport/CMakeLists.txt b/sources/pyside2/tests/QtPrintSupport/CMakeLists.txt index 2f7cb08b9..510c5fe0b 100644 --- a/sources/pyside2/tests/QtPrintSupport/CMakeLists.txt +++ b/sources/pyside2/tests/QtPrintSupport/CMakeLists.txt @@ -1 +1,2 @@ -# Please add some tests, here +PYSIDE_TEST(bug_500.py) +PYSIDE_TEST(returnquadruplesofnumbers_test.py) diff --git a/sources/pyside2/tests/QtGui/bug_500.py b/sources/pyside2/tests/QtPrintSupport/bug_500.py index b6f941633..b6f941633 100644 --- a/sources/pyside2/tests/QtGui/bug_500.py +++ b/sources/pyside2/tests/QtPrintSupport/bug_500.py diff --git a/sources/pyside2/tests/QtWidgets/returnquadruplesofnumbers_test.py b/sources/pyside2/tests/QtPrintSupport/returnquadruplesofnumbers_test.py index 6e4cfeb63..f6f2490f0 100644 --- a/sources/pyside2/tests/QtWidgets/returnquadruplesofnumbers_test.py +++ b/sources/pyside2/tests/QtPrintSupport/returnquadruplesofnumbers_test.py @@ -30,7 +30,7 @@ from __future__ import print_function import unittest from PySide2.QtGui import QTextCursor -from PySide2.QtPrintSupport import QPrinter +from PySide2.QtPrintSupport import QPrinter, QPrinterInfo from PySide2.QtWidgets import QLayout, QWidget, QGraphicsLayout, QGraphicsLayoutItem from helper import UsesQApplication @@ -81,14 +81,22 @@ class ReturnsQuadruplesOfNumbers(UsesQApplication): self.assertEqual(obj.selectedTableCells(), (-1, -1, -1, -1)) def testQPrinterGetPageMargins(self): - # Bug #742 - obj = QPrinter() + # Bug #742. Find a printer like PDF/XPS on which arbitrary margins can be set. + printer = None + for printerInfo in QPrinterInfo.availablePrinters(): + name = printerInfo.printerName().lower() + if "xps" in name or "pdf" in name: + printer = QPrinter(printerInfo) + break + if not printer: + printer = QPrinter() # On macOS the minimum margin of a page is ~12, setting something lower than that will # actually fail to set all the margins. values = (15.0, 16.0, 17.0, 18.0, QPrinter.Point) - obj.setPageMargins(*values) - print(obj.getPageMargins(QPrinter.Point), values[:-1]) - self.assertTrue(self.compareTuples(obj.getPageMargins(QPrinter.Point), values[:-1])) + printer.setPageMargins(*values) + actual = printer.getPageMargins(QPrinter.Point) + print(printer.printerName(), actual, values[:-1]) + self.assertTrue(self.compareTuples(actual, values[:-1])) if __name__ == "__main__": unittest.main() diff --git a/sources/pyside2/tests/QtTest/CMakeLists.txt b/sources/pyside2/tests/QtTest/CMakeLists.txt index 2a95b70f7..cf72dfa5c 100644 --- a/sources/pyside2/tests/QtTest/CMakeLists.txt +++ b/sources/pyside2/tests/QtTest/CMakeLists.txt @@ -2,3 +2,4 @@ PYSIDE_TEST(click_test.py) PYSIDE_TEST(eventfilter_test.py) # The test is currently permanently broken, needs to be fixed. #PYSIDE_TEST(touchevent_test.py) +PYSIDE_TEST(qvalidator_test.py) diff --git a/sources/pyside2/tests/QtWidgets/qvalidator_test.py b/sources/pyside2/tests/QtTest/qvalidator_test.py index dd5eaadb3..dd5eaadb3 100644 --- a/sources/pyside2/tests/QtWidgets/qvalidator_test.py +++ b/sources/pyside2/tests/QtTest/qvalidator_test.py diff --git a/sources/pyside2/tests/QtWidgets/CMakeLists.txt b/sources/pyside2/tests/QtWidgets/CMakeLists.txt index 4efd9d803..fa64d1c3b 100644 --- a/sources/pyside2/tests/QtWidgets/CMakeLists.txt +++ b/sources/pyside2/tests/QtWidgets/CMakeLists.txt @@ -123,13 +123,11 @@ PYSIDE_TEST(qtextedit_signal_test.py) PYSIDE_TEST(qtreeview_test.py) PYSIDE_TEST(qtoolbar_test.py) PYSIDE_TEST(qtoolbox_test.py) -PYSIDE_TEST(qvalidator_test.py) PYSIDE_TEST(qvariant_test.py) PYSIDE_TEST(qwidget_setlayout_test.py) PYSIDE_TEST(qwidget_test.py) PYSIDE_TEST(qcolormap_test.py) PYSIDE_TEST(reference_count_test.py) -PYSIDE_TEST(returnquadruplesofnumbers_test.py) PYSIDE_TEST(standardpixmap_test.py) PYSIDE_TEST(test_module_template.py) PYSIDE_TEST(virtual_protected_inheritance_test.py) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 37b82e99f..1afc7d135 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1053,7 +1053,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte QString nspace; if (names.size() > 1) nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); - typeEntry = new EnumTypeEntry(nspace, enumName, 0); + typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0)); TypeDatabase::instance()->addType(typeEntry); } else if (!enumItem->isAnonymous()) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); @@ -1937,7 +1937,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu metaFunction->setUserAdded(true); AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None; metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::FinalInTargetLang | isStatic); - metaFunction->setType(translateType(addedFunc.version(), addedFunc.returnType())); + metaFunction->setType(translateType(addedFunc.returnType())); QVector<AddedFunction::TypeInfo> args = addedFunc.arguments(); @@ -1946,7 +1946,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu for (int i = 0; i < args.count(); ++i) { AddedFunction::TypeInfo& typeInfo = args[i]; AbstractMetaArgument *metaArg = new AbstractMetaArgument; - AbstractMetaType* type = translateType(addedFunc.version(), typeInfo); + AbstractMetaType *type = translateType(typeInfo); decideUsagePattern(type); metaArg->setType(type); metaArg->setArgumentIndex(i); @@ -2404,8 +2404,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel return metaFunction; } -AbstractMetaType *AbstractMetaBuilderPrivate::translateType(double vr, - const AddedFunction::TypeInfo &typeInfo) +AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction::TypeInfo &typeInfo) { Q_ASSERT(!typeInfo.name.isEmpty()); TypeDatabase* typeDb = TypeDatabase::instance(); @@ -2462,7 +2461,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(double vr, metaType->setConstant(typeInfo.isConstant); if (isTemplate) { for (const QString& templateArg : qAsConst(templateArgs)) { - AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg)); + AbstractMetaType *metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg)); metaType->addInstantiation(metaArgType); } metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 9e15541f6..7a2565914 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -124,7 +124,7 @@ public: QString fixDefaultValue(ArgumentModelItem item, AbstractMetaType *type, AbstractMetaFunction *fnc, AbstractMetaClass *, int argumentIndex); - AbstractMetaType* translateType(double vr, const AddedFunction::TypeInfo &typeInfo); + AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo); AbstractMetaType *translateType(const TypeInfo &type, bool *ok, bool resolveType = true, bool resolveScope = true); diff --git a/sources/shiboken2/ApiExtractor/fileout.cpp b/sources/shiboken2/ApiExtractor/fileout.cpp index be0023c3c..4ee5abd52 100644 --- a/sources/shiboken2/ApiExtractor/fileout.cpp +++ b/sources/shiboken2/ApiExtractor/fileout.cpp @@ -174,6 +174,27 @@ static void diff(QList<QByteArray> a, QList<QByteArray> b) FileOut::State FileOut::done() { + QString errorMessage; + const State result = done(&errorMessage); + if (result == Failure) + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + return result; +} + +QString FileOut::msgCannotOpenForReading(const QFile &f) +{ + return QStringLiteral("Failed to open file '%1' for reading: %2") + .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); +} + +QString FileOut::msgCannotOpenForWriting(const QFile &f) +{ + return QStringLiteral("Failed to open file '%1' for writing: %2") + .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); +} + +FileOut::State FileOut::done(QString *errorMessage) +{ Q_ASSERT(!isDone); if (name.isEmpty()) return Failure; @@ -186,9 +207,7 @@ FileOut::State FileOut::done() QByteArray original; if (info.exists() && (diff || (info.size() == tmp.size()))) { if (!fileRead.open(QIODevice::ReadOnly)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("failed to open file '%1' for reading") - .arg(QDir::toNativeSeparators(fileRead.fileName())); + *errorMessage = msgCannotOpenForReading(fileRead); return Failure; } @@ -203,17 +222,14 @@ FileOut::State FileOut::done() if (!FileOut::dummy) { QDir dir(info.absolutePath()); if (!dir.mkpath(dir.absolutePath())) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unable to create directory '%1'") - .arg(QDir::toNativeSeparators(dir.absolutePath())); + *errorMessage = QStringLiteral("unable to create directory '%1'") + .arg(QDir::toNativeSeparators(dir.absolutePath())); return Failure; } QFile fileWrite(name); if (!fileWrite.open(QIODevice::WriteOnly)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("failed to open file '%1' for writing") - .arg(QDir::toNativeSeparators(fileWrite.fileName())); + *errorMessage = msgCannotOpenForWriting(fileWrite); return Failure; } QTextCodec *codec = QTextCodec::codecForName("UTF-8"); diff --git a/sources/shiboken2/ApiExtractor/fileout.h b/sources/shiboken2/ApiExtractor/fileout.h index 14ce3a251..de08a824c 100644 --- a/sources/shiboken2/ApiExtractor/fileout.h +++ b/sources/shiboken2/ApiExtractor/fileout.h @@ -32,6 +32,8 @@ #include <QtCore/QObject> #include <QtCore/QTextStream> +QT_FORWARD_DECLARE_CLASS(QFile) + class FileOut : public QObject { private: @@ -49,6 +51,10 @@ public: } State done(); + State done(QString *errorMessage); + + static QString msgCannotOpenForReading(const QFile &f); + static QString msgCannotOpenForWriting(const QFile &f); QTextStream stream; diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp index bcc5238bc..9ad846a52 100644 --- a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -36,7 +36,7 @@ void TestAddFunction::testParsingFuncNameAndConstness() { // generic test... const char sig1[] = "func(type1, const type2, const type3* const)"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); QCOMPARE(f1.name(), QLatin1String("func")); QCOMPARE(f1.arguments().count(), 3); AddedFunction::TypeInfo retval = f1.returnType(); @@ -47,7 +47,7 @@ void TestAddFunction::testParsingFuncNameAndConstness() // test with a ugly template as argument and other ugly stuff const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *, const type3* const ) const "; - AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc<int& , C<char*> * > * *"), 0); + AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc<int& , C<char*> * > * *")); QCOMPARE(f2.name(), QLatin1String("_fu__nc_")); QVector< AddedFunction::TypeInfo > args = f2.arguments(); QCOMPARE(args.count(), 4); @@ -64,7 +64,7 @@ void TestAddFunction::testParsingFuncNameAndConstness() // function with no args. const char sig3[] = "func()"; - AddedFunction f3(QLatin1String(sig3), QLatin1String("void"), 0); + AddedFunction f3(QLatin1String(sig3), QLatin1String("void")); QCOMPARE(f3.name(), QLatin1String("func")); QCOMPARE(f3.arguments().count(), 0); } @@ -181,7 +181,7 @@ void TestAddFunction::testAddFunctionCodeSnippets() void TestAddFunction::testAddFunctionWithoutParenteses() { const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); QCOMPARE(f1.name(), QLatin1String("func")); QCOMPARE(f1.arguments().count(), 0); @@ -211,7 +211,7 @@ void TestAddFunction::testAddFunctionWithoutParenteses() void TestAddFunction::testAddFunctionWithDefaultArgs() { const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); QCOMPARE(f1.name(), QLatin1String("func")); QCOMPARE(f1.arguments().count(), 0); @@ -276,7 +276,7 @@ void TestAddFunction::testAddFunctionAtModuleLevel() void TestAddFunction::testAddFunctionWithVarargs() { const char sig1[] = "func(int,char,...)"; - AddedFunction f1( QLatin1String(sig1), QLatin1String("void"), 0); + AddedFunction f1( QLatin1String(sig1), QLatin1String("void")); QCOMPARE(f1.name(), QLatin1String("func")); QCOMPARE(f1.arguments().count(), 3); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 76953a51e..e94d952a3 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -672,15 +672,9 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS return true; } -bool TypeDatabase::checkApiVersion(const QString& package, const QString& version) const +bool TypeDatabase::checkApiVersion(const QString &package, + const QVersionNumber &versionNumber) const { - const QVersionNumber versionNumber = QVersionNumber::fromString(version); - if (versionNumber.isNull()) { - qCWarning(lcShiboken).noquote().nospace() - << "checkApiVersion: Invalid version \"" << version << "\" specified for package " - << package << '.'; - return false; - } const ApiVersions &versions = *apiVersions(); for (int i = 0, size = versions.size(); i < size; ++i) { if (versions.at(i).first.match(package).hasMatch()) diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index dfddfc300..30d261d35 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -39,6 +39,7 @@ #include <QtCore/QStringList> QT_FORWARD_DECLARE_CLASS(QIODevice) +QT_FORWARD_DECLARE_CLASS(QVersionNumber) class ComplexTypeEntry; class ContainerTypeEntry; @@ -148,7 +149,7 @@ public: bool setApiVersion(const QString& package, const QString& version); - bool checkApiVersion(const QString& package, const QString &version) const; + bool checkApiVersion(const QString &package, const QVersionNumber &version) const; bool hasDroppedTypeEntries() const { return !m_dropTypeEntries.isEmpty(); } diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 69dccbb86..600536aba 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -215,6 +215,17 @@ static QString msgReaderError(const QXmlStreamReader &reader) return msgReaderError(reader, reader.errorString()); } +static QString msgInvalidVersion(const QStringRef &version, const QString &package = QString()) +{ + QString result; + QTextStream str(&result); + str << "Invalid version \"" << version << '"'; + if (!package.isEmpty()) + str << "\" specified for package " << package; + str << '.'; + return result; +} + bool Handler::parse(QXmlStreamReader &reader) { m_error.clear(); @@ -605,7 +616,8 @@ static QString checkSignatureError(const QString& signature, const QString& tag) } void Handler::addFlags(const QString &name, QString flagName, - const QHash<QString, QString> &attributes, double since) + const QHash<QString, QString> &attributes, + const QVersionNumber &since) { FlagsTypeEntry *ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), since); ftype->setOriginator(m_currentEnum); @@ -640,7 +652,7 @@ void Handler::addFlags(const QString &name, QString flagName, bool Handler::handleSmartPointerEntry(StackElement *element, QHash<QString, QString> &attributes, const QString &name, - double since) + const QVersionNumber &since) { QString smartPointerType = attributes[QLatin1String("type")]; if (smartPointerType.isEmpty()) { @@ -692,9 +704,19 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return true; } - if (!m_defaultPackage.isEmpty() && atts.hasAttribute(sinceAttribute())) { + QVersionNumber since(0, 0); + const QStringRef sinceSpec = atts.value(sinceAttribute()); + if (!sinceSpec.isNull()) { + since = QVersionNumber::fromString(sinceSpec.toString()); + if (since.isNull()) { + m_error = msgInvalidVersion(sinceSpec, m_defaultPackage); + return false; + } + } + + if (!m_defaultPackage.isEmpty() && since > QVersionNumber(0, 0)) { TypeDatabase* td = TypeDatabase::instance(); - if (!td->checkApiVersion(m_defaultPackage, atts.value(sinceAttribute()).toString())) { + if (!td->checkApiVersion(m_defaultPackage, since)) { ++m_ignoreDepth; return true; } @@ -734,7 +756,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts QHash<QString, QString> attributes; attributes.insert(nameAttribute(), QString()); attributes.insert(QLatin1String("revision"), QLatin1String("0")); - attributes.insert(sinceAttribute(), QLatin1String("0")); + attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes switch (element->type) { case StackElement::PrimitiveTypeEntry: @@ -798,7 +820,6 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts fetchAttributeValues(tagName, atts, &attributes); QString name = attributes[nameAttribute()]; - double since = attributes[sinceAttribute()].toDouble(); if (m_database->hasDroppedTypeEntries()) { QString identifier = getNamePrefix(element) + QLatin1Char('.'); @@ -1097,7 +1118,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts QHash<QString, QString> attributes; attributes.insert(QLatin1String("mode"), QLatin1String("replace")); attributes.insert(QLatin1String("format"), QLatin1String("native")); - attributes.insert(sinceAttribute(), QLatin1String("0")); + attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes fetchAttributeValues(tagName, atts, &attributes); @@ -1144,7 +1165,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts // check the XML tag attributes QHash<QString, QString> attributes; attributes.insert(xPathAttribute(), QString()); - attributes.insert(sinceAttribute(), QLatin1String("0")); + attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes fetchAttributeValues(tagName, atts, &attributes); const int validParent = StackElement::TypeEntryMask @@ -1179,7 +1200,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts element->entry = topElement.entry; QHash<QString, QString> attributes; - attributes.insert(sinceAttribute(), QLatin1String("0")); + attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes switch (element->type) { case StackElement::Root: attributes.insert(QLatin1String("package"), QString()); @@ -1309,11 +1330,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts { }; }; - double since = 0; - if (attributes.count() > 0) { + if (!attributes.isEmpty()) fetchAttributeValues(tagName, atts, &attributes); - since = attributes[sinceAttribute()].toDouble(); - } switch (element->type) { case StackElement::Root: @@ -1718,7 +1736,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } - AddedFunction func(signature, attributes[QLatin1String("return-type")], since); + AddedFunction func(signature, attributes[QLatin1String("return-type")]); func.setStatic(attributes[QLatin1String("static")] == yesAttributeValue()); if (!signature.contains(QLatin1Char('('))) signature += QLatin1String("()"); @@ -2082,7 +2100,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return true; } -PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, double vr) : +PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr) : TypeEntry(name, PrimitiveType, vr), m_preferredConversion(true), m_preferredTargetLangType(true) @@ -2471,8 +2489,7 @@ static AddedFunction::TypeInfo parseType(const QString& signature, int startPos return result; } -AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : - m_version(vr), +AddedFunction::AddedFunction(QString signature, const QString &returnType) : m_access(Public) { Q_ASSERT(!returnType.isEmpty()); @@ -2540,7 +2557,8 @@ AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& si return parseType(signature); } -ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, double vr) : +ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, + const QVersionNumber &vr) : TypeEntry(QString(name).replace(QLatin1String(".*::"), QString()), t, vr), m_qualifiedCppName(name), m_qobject(false), @@ -2581,7 +2599,7 @@ bool StringTypeEntry::isNativeIdBased() const return false; } -CharTypeEntry::CharTypeEntry(const QString &name, double vr) : +CharTypeEntry::CharTypeEntry(const QString &name, const QVersionNumber &vr) : ValueTypeEntry(name, CharType, vr) { setCodeGeneration(GenerateNothing); @@ -2606,7 +2624,7 @@ bool CharTypeEntry::isNativeIdBased() const return false; } -VariantTypeEntry::VariantTypeEntry(const QString &name, double vr) : +VariantTypeEntry::VariantTypeEntry(const QString &name, const QVersionNumber &vr) : ValueTypeEntry(name, VariantType, vr) { } @@ -2695,7 +2713,7 @@ bool TypeEntry::isCppPrimitive() const typedef QHash<const TypeEntry*, CustomConversion*> TypeEntryCustomConversionMap; Q_GLOBAL_STATIC(TypeEntryCustomConversionMap, typeEntryCustomConversionMap); -TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, double vr) : +TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr) : m_name(name), m_type(t), m_version(vr) @@ -2729,27 +2747,27 @@ CustomConversion* TypeEntry::customConversion() const return 0; } -TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, double vr) : +TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr) : TypeEntry(name, TypeSystemType, vr) { } VoidTypeEntry::VoidTypeEntry() : - TypeEntry(QLatin1String("void"), VoidType, 0) + TypeEntry(QLatin1String("void"), VoidType, QVersionNumber(0, 0)) { } VarargsTypeEntry::VarargsTypeEntry() : - TypeEntry(QLatin1String("..."), VarargsType, 0) + TypeEntry(QLatin1String("..."), VarargsType, QVersionNumber(0, 0)) { } -TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, double vr) : +TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, const QVersionNumber &vr) : TypeEntry(name, TemplateArgumentType, vr) { } -ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, double vr) : +ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr) : TypeEntry(QLatin1String("Array"), ArrayType, vr), m_nestedType(nested_type) { @@ -2769,7 +2787,8 @@ QString ArrayTypeEntry::targetLangApiName() const return QLatin1String("jobjectArray"); } -EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName, double vr) : +EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName, + const QVersionNumber &vr) : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, EnumType, vr), m_qualifier(nspace), @@ -2792,19 +2811,22 @@ QString EnumTypeEntry::targetLangName() const return m_targetLangName; } -EnumValueTypeEntry::EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr) : +EnumValueTypeEntry::EnumValueTypeEntry(const QString &name, const QString &value, + const EnumTypeEntry *enclosingEnum, + const QVersionNumber &vr) : TypeEntry(name, TypeEntry::EnumValue, vr), m_value(value), m_enclosingEnum(enclosingEnum) { } -FlagsTypeEntry::FlagsTypeEntry(const QString &name, double vr) : +FlagsTypeEntry::FlagsTypeEntry(const QString &name, const QVersionNumber &vr) : TypeEntry(name, FlagsType, vr) { } -ContainerTypeEntry::ContainerTypeEntry(const QString &name, Type type, double vr) : +ContainerTypeEntry::ContainerTypeEntry(const QString &name, Type type, + const QVersionNumber &vr) : ComplexTypeEntry(name, ContainerType, vr), m_type(type) { @@ -2815,7 +2837,7 @@ SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &name, const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, - double vr) : + const QVersionNumber &vr) : ComplexTypeEntry(name, SmartPointerType, vr), m_getterName(getterName), m_smartPointerType(smartPointerType), @@ -2823,12 +2845,12 @@ SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &name, { } -NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, double vr) : +NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, const QVersionNumber &vr) : ComplexTypeEntry(name, NamespaceType, vr) { } -ValueTypeEntry::ValueTypeEntry(const QString &name, double vr) : +ValueTypeEntry::ValueTypeEntry(const QString &name, const QVersionNumber &vr) : ComplexTypeEntry(name, BasicValueType, vr) { } @@ -2843,12 +2865,12 @@ bool ValueTypeEntry::isNativeIdBased() const return true; } -ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, double vr) : +ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr) : ComplexTypeEntry(name, t, vr) { } -StringTypeEntry::StringTypeEntry(const QString &name, double vr) : +StringTypeEntry::StringTypeEntry(const QString &name, const QVersionNumber &vr) : ValueTypeEntry(name, StringType, vr) { setCodeGeneration(GenerateNothing); @@ -3007,7 +3029,7 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, double vr) : +InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, const QVersionNumber &vr) : ComplexTypeEntry(name, InterfaceType, vr) { } @@ -3024,13 +3046,13 @@ QString InterfaceTypeEntry::qualifiedCppName() const } FunctionTypeEntry::FunctionTypeEntry(const QString &name, const QString &signature, - double vr) : + const QVersionNumber &vr) : TypeEntry(name, FunctionType, vr) { addSignature(signature); } -ObjectTypeEntry::ObjectTypeEntry(const QString &name, double vr) +ObjectTypeEntry::ObjectTypeEntry(const QString &name, const QVersionNumber &vr) : ComplexTypeEntry(name, ObjectType, vr) { } diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 62d348f69..2f534c93d 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -40,6 +40,7 @@ #include <QtCore/QStringList> #include <QtCore/QMap> #include <QtCore/QVector> +#include <QtCore/QVersionNumber> //Used to identify the conversion rule to avoid break API #define TARGET_CONVERSION_RULE_FLAG "0" @@ -415,7 +416,7 @@ struct AddedFunction }; /// Creates a new AddedFunction with a signature and a return type. - explicit AddedFunction(QString signature, QString returnType, double vr); + explicit AddedFunction(QString signature, const QString &returnType); AddedFunction() = default; /// Returns the function name. @@ -466,15 +467,10 @@ struct AddedFunction return m_isStatic; } - double version() const - { - return m_version; - } private: QString m_name; QVector<TypeInfo> m_arguments; TypeInfo m_returnType; - double m_version = 0; Access m_access = Protected; bool m_isConst = false; bool m_isStatic = false; @@ -573,7 +569,7 @@ public: }; Q_ENUM(CodeGeneration) - explicit TypeEntry(const QString &name, Type t, double vr); + explicit TypeEntry(const QString &name, Type t, const QVersionNumber &vr); virtual ~TypeEntry(); @@ -867,7 +863,7 @@ public: return !m_conversionRule.isEmpty(); } - double version() const + QVersionNumber version() const { return m_version; } @@ -903,13 +899,13 @@ private: QHash<QString, bool> m_includesUsed; QString m_conversionRule; bool m_stream = false; - double m_version; + QVersionNumber m_version; }; class TypeSystemTypeEntry : public TypeEntry { public: - explicit TypeSystemTypeEntry(const QString &name, double vr); + explicit TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr); }; class VoidTypeEntry : public TypeEntry @@ -927,7 +923,7 @@ public: class TemplateArgumentEntry : public TypeEntry { public: - explicit TemplateArgumentEntry(const QString &name, double vr); + explicit TemplateArgumentEntry(const QString &name, const QVersionNumber &vr); int ordinal() const { @@ -945,7 +941,7 @@ private: class ArrayTypeEntry : public TypeEntry { public: - explicit ArrayTypeEntry(const TypeEntry *nested_type, double vr); + explicit ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr); void setNestedTypeEntry(TypeEntry *nested) { @@ -967,7 +963,7 @@ private: class PrimitiveTypeEntry : public TypeEntry { public: - explicit PrimitiveTypeEntry(const QString &name, double vr); + explicit PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr); QString targetLangName() const override; void setTargetLangName(const QString &targetLangName) @@ -1051,7 +1047,8 @@ public: EnumClass // C++ 11 : enum class Foo { value1, value2 } }; - explicit EnumTypeEntry(const QString &nspace, const QString &enumName, double vr); + explicit EnumTypeEntry(const QString &nspace, const QString &enumName, + const QVersionNumber &vr); QString targetLangPackage() const override; void setTargetLangPackage(const QString &package); @@ -1164,7 +1161,7 @@ private: class EnumValueTypeEntry : public TypeEntry { public: - explicit EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr); + explicit EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, const QVersionNumber &vr); QString value() const { return m_value; } const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } @@ -1176,7 +1173,7 @@ private: class FlagsTypeEntry : public TypeEntry { public: - explicit FlagsTypeEntry(const QString &name, double vr); + explicit FlagsTypeEntry(const QString &name, const QVersionNumber &vr); QString qualifiedTargetLangName() const override; QString targetLangName() const override; @@ -1240,7 +1237,7 @@ public: Unknown }; - explicit ComplexTypeEntry(const QString &name, Type t, double vr); + explicit ComplexTypeEntry(const QString &name, Type t, const QVersionNumber &vr); bool isComplex() const override; @@ -1458,7 +1455,7 @@ public: }; Q_ENUM(Type) - explicit ContainerTypeEntry(const QString &name, Type type, double vr); + explicit ContainerTypeEntry(const QString &name, Type type, const QVersionNumber &vr); Type type() const { @@ -1501,7 +1498,7 @@ public: const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, - double vr); + const QVersionNumber &vr); QString getter() const { @@ -1522,28 +1519,28 @@ private: class NamespaceTypeEntry : public ComplexTypeEntry { public: - explicit NamespaceTypeEntry(const QString &name, double vr); + explicit NamespaceTypeEntry(const QString &name, const QVersionNumber &vr); }; class ValueTypeEntry : public ComplexTypeEntry { public: - explicit ValueTypeEntry(const QString &name, double vr); + explicit ValueTypeEntry(const QString &name, const QVersionNumber &vr); bool isValue() const override; bool isNativeIdBased() const override; protected: - explicit ValueTypeEntry(const QString &name, Type t, double vr); + explicit ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr); }; class StringTypeEntry : public ValueTypeEntry { public: - explicit StringTypeEntry(const QString &name, double vr); + explicit StringTypeEntry(const QString &name, const QVersionNumber &vr); QString targetLangApiName() const override; QString targetLangName() const override; @@ -1555,7 +1552,7 @@ public: class CharTypeEntry : public ValueTypeEntry { public: - explicit CharTypeEntry(const QString &name, double vr); + explicit CharTypeEntry(const QString &name, const QVersionNumber &vr); QString targetLangApiName() const override; QString targetLangName() const override; @@ -1567,7 +1564,7 @@ public: class VariantTypeEntry: public ValueTypeEntry { public: - explicit VariantTypeEntry(const QString &name, double vr); + explicit VariantTypeEntry(const QString &name, const QVersionNumber &vr); QString targetLangApiName() const override; QString targetLangName() const override; @@ -1580,7 +1577,7 @@ public: class InterfaceTypeEntry : public ComplexTypeEntry { public: - explicit InterfaceTypeEntry(const QString &name, double vr); + explicit InterfaceTypeEntry(const QString &name, const QVersionNumber &vr); static QString interfaceName(const QString &name) { @@ -1607,7 +1604,8 @@ private: class FunctionTypeEntry : public TypeEntry { public: - explicit FunctionTypeEntry(const QString& name, const QString& signature, double vr); + explicit FunctionTypeEntry(const QString& name, const QString& signature, + const QVersionNumber &vr); void addSignature(const QString& signature) { m_signatures << signature; @@ -1629,7 +1627,7 @@ private: class ObjectTypeEntry : public ComplexTypeEntry { public: - explicit ObjectTypeEntry(const QString &name, double vr); + explicit ObjectTypeEntry(const QString &name, const QVersionNumber &vr); InterfaceTypeEntry *designatedInterface() const override; void setDesignatedInterface(InterfaceTypeEntry *entry) diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h index d3485726e..d4707acb7 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_p.h +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -145,7 +145,7 @@ private: bool handleSmartPointerEntry(StackElement *element, QHash<QString, QString> &attributes, const QString &name, - double since); + const QVersionNumber &since); bool endElement(const QStringRef& localName); template <class String> // QString/QStringRef bool characters(const String &ch); @@ -154,7 +154,8 @@ private: bool importFileElement(const QXmlStreamAttributes &atts); void addFlags(const QString &name, QString flagName, - const QHash<QString, QString> &attributes, double since); + const QHash<QString, QString> &attributes, + const QVersionNumber &since); TypeDatabase* m_database; StackElement* m_current; diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt index d9e110d6d..e774a172b 100644 --- a/sources/shiboken2/CMakeLists.txt +++ b/sources/shiboken2/CMakeLists.txt @@ -50,7 +50,7 @@ macro(get_llvm_config) " OUTPUT_VARIABLE LLVM_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE) - message("LLMV_CONFIG: " ${LLVM_CONFIG}) + message("LLVM_CONFIG: " ${LLVM_CONFIG}) endmacro() set(CLANG_DIR "") diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h index f0b2a5e41..98f3ce4b8 100644 --- a/sources/shiboken2/generator/generator.h +++ b/sources/shiboken2/generator/generator.h @@ -366,7 +366,7 @@ protected: * for which the file name must be returned * \return the file name used to write the binding code for the class */ - virtual QString fileNamePrefix() const = 0; + virtual QString fileNameSuffix() const = 0; virtual QString fileNameForContext(GeneratorContext &context) const = 0; diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 7cce97ae1..842c68b90 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -157,6 +157,14 @@ static QTextStream &ensureEndl(QTextStream &s) return s; } +static void formatSince(QTextStream &s, const char *what, const TypeEntry *te) +{ + if (te && te->version() > QVersionNumber(0, 0)) { + s << ".. note:: This " << what << " was introduced in Qt " + << te->version().toString() << '.' << endl; + } +} + static QString msgTagWarning(const QXmlStreamReader &reader, const QString &context, const QString &tag, const QString &message) { @@ -1133,11 +1141,12 @@ void QtXmlToSphinx::Table::normalize() if (cell.rowSpan > 0) { QtXmlToSphinx::TableCell newCell; newCell.rowSpan = -1; - int max = std::min(cell.rowSpan - 1, count()); + int targetRow = row + 1; + const int targetEndRow = + std::min(targetRow + cell.rowSpan - 1, count()); cell.rowSpan = 0; - for (int i = 0; i < max; ++i) { - self[row+i+1].insert(col, newCell); - } + for ( ; targetRow < targetEndRow; ++targetRow) + self[targetRow].insert(col, newCell); row++; } } @@ -1275,7 +1284,7 @@ QtDocGenerator::~QtDocGenerator() delete m_docParser; } -QString QtDocGenerator::fileNamePrefix() const +QString QtDocGenerator::fileNameSuffix() const { return QLatin1String(".rst"); } @@ -1284,11 +1293,11 @@ QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); if (!context.forSmartPointer()) { - return getClassTargetFullName(metaClass, false) + fileNamePrefix(); + return getClassTargetFullName(metaClass, false) + fileNameSuffix(); } else { const AbstractMetaType *smartPointerType = context.preciseType(); QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); + return fileNameBase + fileNameSuffix(); } } @@ -1368,8 +1377,7 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex writeInheritedByList(s, metaClass, classes()); - if (metaClass->typeEntry() && (metaClass->typeEntry()->version() != 0)) - s << ".. note:: This class was introduced in Qt " << metaClass->typeEntry()->version() << endl; + formatSince(s, "class", metaClass->typeEntry()); writeFunctionList(s, metaClass); @@ -1490,9 +1498,7 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas for (AbstractMetaEnum *en : enums) { s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; writeFormattedText(s, en->documentation(), cppClass); - - if (en->typeEntry() && (en->typeEntry()->version() != 0)) - s << ".. note:: This enum was introduced or modified in Qt " << en->typeEntry()->version() << endl; + formatSince(s, "enum", en->typeEntry()); } } @@ -1807,8 +1813,7 @@ void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const Abstract writeFunctionSignature(s, cppClass, func); s << endl; - if (func->typeEntry() && (func->typeEntry()->version() != 0)) - s << ".. note:: This method was introduced in Qt " << func->typeEntry()->version() << endl; + formatSince(s, "method", func->typeEntry()); if (writeDoc) { s << endl; diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index af26b7fab..9f08a4e8d 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -210,14 +210,14 @@ public: QString docDataDir() const { return m_docDataDir; } - bool doSetup(const QMap<QString, QString>& args); + bool doSetup(const QMap<QString, QString>& args) override; - const char* name() const + const char* name() const override { return "QtDocGenerator"; } - OptionDescriptions options() const; + OptionDescriptions options() const override; QStringList codeSnippetDirs() const { @@ -225,13 +225,13 @@ public: } protected: - QString fileNamePrefix() const; - QString fileNameForContext(GeneratorContext &context) const; - void generateClass(QTextStream &s, GeneratorContext &classContext); - bool finishGeneration(); + QString fileNameSuffix() const override; + QString fileNameForContext(GeneratorContext &context) const override; + void generateClass(QTextStream &s, GeneratorContext &classContext) override; + bool finishGeneration() override; - void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {} - void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {} + void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const override {} + void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const override {} private: void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index be42adb0f..18670eae6 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -135,7 +135,7 @@ CppGenerator::CppGenerator() m_mpFuncs.insert(QLatin1String("__msetitem__"), QLatin1String("mp_ass_subscript")); } -QString CppGenerator::fileNamePrefix() const +QString CppGenerator::fileNameSuffix() const { return QLatin1String("_wrapper.cpp"); } @@ -146,11 +146,11 @@ QString CppGenerator::fileNameForContext(GeneratorContext &context) const if (!context.forSmartPointer()) { QString fileNameBase = metaClass->qualifiedCppName().toLower(); fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); - return fileNameBase + fileNamePrefix(); + return fileNameBase + fileNameSuffix(); } else { const AbstractMetaType *smartPointerType = context.preciseType(); QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); + return fileNameBase + fileNameSuffix(); } } diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index cce1842ab..52da437ee 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -39,7 +39,7 @@ class CppGenerator : public ShibokenGenerator public: CppGenerator(); protected: - QString fileNamePrefix() const override; + QString fileNameSuffix() const override; QString fileNameForContext(GeneratorContext &context) const override; QVector<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, uint query); diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index a033cb69a..3b32825f3 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -37,7 +37,7 @@ #include <QtCore/QVariant> #include <QtCore/QDebug> -QString HeaderGenerator::fileNamePrefix() const +QString HeaderGenerator::fileNameSuffix() const { return QLatin1String("_wrapper.h"); } @@ -48,11 +48,11 @@ QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const if (!context.forSmartPointer()) { QString fileNameBase = metaClass->qualifiedCppName().toLower(); fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); - return fileNameBase + fileNamePrefix(); + return fileNameBase + fileNameSuffix(); } else { const AbstractMetaType *smartPointerType = context.preciseType(); QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); + return fileNameBase + fileNameSuffix(); } } diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.h b/sources/shiboken2/generator/shiboken2/headergenerator.h index d9dc8ffe8..b6596967c 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.h +++ b/sources/shiboken2/generator/shiboken2/headergenerator.h @@ -43,7 +43,7 @@ class HeaderGenerator : public ShibokenGenerator public: OptionDescriptions options() const override { return OptionDescriptions(); } protected: - QString fileNamePrefix() const override; + QString fileNameSuffix() const override; QString fileNameForContext(GeneratorContext &context) const override; void generateClass(QTextStream& s, GeneratorContext &classContext) override; bool finishGeneration() override; diff --git a/sources/shiboken2/libshiboken/qapp_macro.cpp b/sources/shiboken2/libshiboken/qapp_macro.cpp index b31e98d06..9b940aaaa 100644 --- a/sources/shiboken2/libshiboken/qapp_macro.cpp +++ b/sources/shiboken2/libshiboken/qapp_macro.cpp @@ -97,9 +97,10 @@ reset_qApp_var() for (mod_ptr = qApp_moduledicts; *mod_ptr != NULL; mod_ptr++) { // We respect whatever the user may have set. - if (PyDict_GetItem(*mod_ptr, qApp_var) == NULL) + if (PyDict_GetItem(*mod_ptr, qApp_var) == NULL) { if (PyDict_SetItem(*mod_ptr, qApp_var, qApp_content) < 0) return -1; + } } return 0; } @@ -157,7 +158,9 @@ setup_qApp_var(PyObject *module) qApp_var = Py_BuildValue("s", "qApp"); if (qApp_var == NULL) return -1; + // This is a borrowed reference qApp_moduledicts[0] = PyEval_GetBuiltins(); + Py_INCREF(qApp_content); init_done = 1; } @@ -165,7 +168,9 @@ setup_qApp_var(PyObject *module) // into __builtins__, to let it appear like a real macro. module_index = qApp_module_index(module); if (module_index) { + // This line gets a borrowed reference qApp_moduledicts[module_index] = PyModule_GetDict(module); + Py_INCREF(qApp_content); if (reset_qApp_var() < 0) return -1; } |