diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-02 08:14:52 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-02 08:14:52 +0200 |
commit | 4457d68912bea52d34f12224a78c3231377958af (patch) | |
tree | 5eaa5f160a911f144af570646dd0306d8862aeeb | |
parent | 44502f016ac69620fd5d1cf6c26a02eca5cdc8cf (diff) | |
parent | c246633b49f0551de4ae052cfe0f4f9dcdde579e (diff) |
Merge remote-tracking branch 'origin/5.12' into 5.13
Change-Id: I7fc1857f15ccf5d9667dd6d6adb8208c775c6722
35 files changed, 574 insertions, 263 deletions
diff --git a/coin_build_instructions.py b/coin_build_instructions.py index e4a27d264..d094d5b2a 100644 --- a/coin_build_instructions.py +++ b/coin_build_instructions.py @@ -116,6 +116,8 @@ def call_setup(python_ver): "--verbose-build"] if python_ver == "3": cmd += ["--limited-api=yes"] + else: + cmd += ["--skip-docs"] # 1.4.2019: errors in sphinx_build on openSUSE 4.2 if is_snapshot_build(): cmd += ["--snapshot-build"] diff --git a/examples/widgets/dialogs/classwizard/classwizard.py b/examples/widgets/dialogs/classwizard/classwizard.py index 52b4c679e..fc2feb498 100644 --- a/examples/widgets/dialogs/classwizard/classwizard.py +++ b/examples/widgets/dialogs/classwizard/classwizard.py @@ -1,4 +1,4 @@ - +# -*- coding: utf-8 -*- ############################################################################# ## ## Copyright (C) 2013 Riverbank Computing Limited. @@ -40,6 +40,7 @@ ## ############################################################################# +from __future__ import unicode_literals from PySide2 import QtCore, QtGui, QtWidgets import classwizard_rc @@ -127,7 +128,7 @@ class ClassWizard(QtWidgets.QWizard): "Cannot write file %s:\n%s" % (headerFile.fileName(), headerFile.errorString())) return - headerFile.write(str(block)) + headerFile.write(QtCore.QByteArray(block.encode("utf-8"))) block = '' @@ -180,7 +181,7 @@ class ClassWizard(QtWidgets.QWizard): "Cannot write file %s:\n%s" % (implementationFile.fileName(), implementationFile.errorString())) return - implementationFile.write(str(block)) + implementationFile.write(QtCore.QByteArray(block.encode("utf-8"))) super(ClassWizard, self).accept() diff --git a/missing_bindings.py b/missing_bindings.py index dfd94912d..8f3c0b808 100644 --- a/missing_bindings.py +++ b/missing_bindings.py @@ -217,6 +217,8 @@ qt_documentation_website_prefixes['5.8'] = 'http://doc.qt.io/qt-5.8/' qt_documentation_website_prefixes['5.9'] = 'http://doc.qt.io/qt-5.9/' qt_documentation_website_prefixes['5.10'] = 'http://doc.qt.io/qt-5.10/' 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['dev'] = 'http://doc-snapshots.qt.io/qt5-dev/' @@ -239,8 +241,8 @@ parser.add_argument("module", help="the Qt module for which to get the missing types") parser.add_argument("--qt-version", "-v", - default='5.11', - choices=['5.6', '5.9', '5.11', 'dev'], + default='5.12', + choices=['5.6', '5.9', '5.11', '5.12', 'dev'], type=str, dest='version', help="the Qt version to use to check for types") diff --git a/sources/pyside2/doc/_themes/pysidedocs/static/pysidelogo.png b/sources/pyside2/doc/_themes/pysidedocs/static/pysidelogo.png Binary files differindex 882a004dd..3a2f2bd17 100644 --- a/sources/pyside2/doc/_themes/pysidedocs/static/pysidelogo.png +++ b/sources/pyside2/doc/_themes/pysidedocs/static/pysidelogo.png diff --git a/sources/pyside2/doc/contents.rst b/sources/pyside2/doc/contents.rst index 35dc9f5f2..d6b7f6ffb 100644 --- a/sources/pyside2/doc/contents.rst +++ b/sources/pyside2/doc/contents.rst @@ -4,6 +4,8 @@ .. toctree:: :maxdepth: 2 + overview.rst + faq.rst gettingstarted.rst tutorials/index.rst pysideapi2.rst diff --git a/sources/pyside2/doc/faq.rst b/sources/pyside2/doc/faq.rst new file mode 100644 index 000000000..e09d98999 --- /dev/null +++ b/sources/pyside2/doc/faq.rst @@ -0,0 +1,49 @@ +Frequently Asked Questions +========================== + +**When was PySide2 adopted by The Qt Company?** + During April 2016 `The Qt Company <https://qt.io>`_ decided to properly support the port + (`see details <https://groups.google.com/forum/#!topic/pyside-dev/pqwzngAGLWE>`_). + +**PySide? Qt for Python? what is the name?** + The name of the project is Qt for Python and the name of the module is PySide2. + +**Why PySide2 and not just PySide?** + Since PySide was developed for Qt4, when the port was made to support Qt5, + the name is changed to PySide2 to imply that it was a newer version. + +**Where I can find information about the old PySide project?** + The old wiki page of the project is available on PySide, but the project is deprecated + and there is no official support for it. We highly recommend not to use it. + +**My project is using PySide, how hard would it be to adapt it to PySide2?** + The changes are the same as between Qt4 and Qt5, and for PySide users it mostly means + adapting the import statements since many classes were moved from QtGui to QtWidgets. + Qt 5 is highly compatible with Qt 4. It is possible for developers of Qt 4 applications to + seamlessly move to Qt 5 with their current functionality and gradually develop new things, + leveraging all the great items Qt 5 makes possible. + +**Does PySide2 support Android and iOS development / deployment?** + At the moment there is no support for mobile platforms. + +**Does PySide2 have support for embedded Linux (Raspberry Pi, i.MX6 etc)?** + Not at the moment. + +**There are three wheels (pyside2, shiboken2, and shiboken2_generator) + what is the different between them?** + + Before the official release, everything was in one big wheel, but it made sense to split + the projects in three different wheels: + * **pyside2**: contains all the PySide2 modules to use the Qt framework. + Also depends on the shiboken2 module. + * **shiboken2**: contains the shiboken2 module with helper functions for PySide2. + * **shiboken2_generator**: contains the generator binary that can work with a C++ project + and a typesystem to generate Python bindings. + Take into account that if you want to generate bindings for a Qt/C++ project, + the linking to the Qt shared libraries will be missing, and you will need to do this by hand. + We recommend to build PySide2 from scratch to have everything properly linked. + +**Why shiboken2_generator is not installed automatically?** + It's not necessary to install it to use PySide2. + The package is the result of the wheel splitting process. + To use the generator, it's recommended to build it from scratch to have the proper Qt-linking. diff --git a/sources/pyside2/doc/gettingstarted.rst b/sources/pyside2/doc/gettingstarted.rst index 0a58226a7..cc915a5cb 100644 --- a/sources/pyside2/doc/gettingstarted.rst +++ b/sources/pyside2/doc/gettingstarted.rst @@ -2,13 +2,21 @@ Getting Started =============== -To get started with |project|, install the following prerequisites: +To develop with |project|, you must install Python, Clang, and |project|. + +Preparing for the Installation +============================== + +Before you can install |project|, you must install the following software: * Python 3.5+ or 2.7 * libclang 5.0+ (for Qt 5.11) or 6.0+ (for Qt 5.12) * Recommended: a virtual environment, such as `venv <https://docs.python.org/3/library/venv.html>`_ or `virtualenv <https://virtualenv.pypa.io/en/stable/installation>`_ -With these installed, you are ready to install the |project| +Installing |project| +==================== + +After you have installed the required software, you are ready to install the |project| packages using the pip wheel. Run the following command from your command prompt to install:: @@ -18,6 +26,9 @@ or:: pip install --index-url=http://download.qt.io/snapshots/ci/pyside/5.12/latest pyside2 --trusted-host download.qt.io +Testing the Installation +======================== + Now that you have |project| installed, you can test your setup by running the following Python constructs to print version information: @@ -25,6 +36,9 @@ constructs to print version information: :start-line: 5 :end-line: 32 +Creating a Simple Application +============================= + Your |project| setup is ready, so try exploring it further by developing a simple application that prints "Hello World" in several languages. The following instructions will guide you through the development process: diff --git a/sources/pyside2/doc/index.rst b/sources/pyside2/doc/index.rst index 7f3b8e4a7..b0bb1d19c 100644 --- a/sources/pyside2/doc/index.rst +++ b/sources/pyside2/doc/index.rst @@ -3,7 +3,9 @@ |project| offers Python bindings for Qt, enabling the use of Qt5 APIs in Python applications. It lets Python developers utilize the full potential of Qt, using -the |pymodname| module. The |pymodname| module provides access to the individual +the |pymodname| module. + +The |pymodname| module provides access to the individual Qt modules such as QtCore, QtGui, and so on. |project| also comes with the :doc:`Shiboken2 <shiboken2:index>` CPython binding code generator, which can be used to generate Python bindings for your C or C++ code. @@ -18,94 +20,68 @@ used to generate Python bindings for your C or C++ code. Qt Modules =========== -.. list-table:: - :widths: 150, 150 - :align: left - - * - `Qt Core <PySide2/QtCore/index.html>`_ - Provides core non-GUI functionality. - - `Qt 3D Animation <PySide2/Qt3DAnimation/index.html>`_ - Provides basic elements required to animate 3D objects. - * - `Qt Gui <PySide2/QtGui/index.html>`_ - Extends QtCore with GUI functionality. - - `Qt Help <PySide2/QtHelp/index.html>`_ - Provides classes for integrating online documentation in applications. - * - `Qt Network <PySide2/QtNetwork/index.html>`_ - Offers classes that lets you to write TCP/IP clients and servers. - - `Qt OpenGL <PySide2/QtOpenGL/index.html>`_ - Offers classes that make it easy to use OpenGL in Qt applications. - * - `Qt PrintSupport <PySide2/QtPrintSupport/index.html>`_ - Provides extensive cross-platform support for printing. - - `Qt Qml <PySide2/QtQml/index.html>`_ - Python API for Qt QML. - * - `Qt Charts <PySide2/QtCharts/index.html>`_ - Provides a set of easy to use chart components. - - `Qt Quick <PySide2/QtQuick/index.html>`_ - Provides classes for embedding Qt Quick in Qt applications. - * - `Qt DataVisualization <PySide2/QtDataVisualization/index.html>`_ - Provides a way to visualize data in 3D as bar, scatter, and surface graphs. - - `Qt QuickWidgets <PySide2/QtQuickWidgets/index.html>`_ - Provides the QQuickWidget class for embedding Qt Quick in widget-based applications. - * - `Qt TextToSpeech <PySide2/QtTextToSpeech/index.html>`_ - Provides API to access text-to-speech engines. - - `Qt Sql <PySide2/QtSql/index.html>`_ - Helps you provide seamless database integration to your Qt applications. - * - `Qt Multimedia <PySide2/QtMultimedia/index.html>`_ - Provides low-level multimedia functionality. - - `Qt MultimediaWidgets <PySide2/QtMultimediaWidgets/index.html>`_ - Provides the widget-based multimedia API. - * - `Qt MacExtras <PySide2/QtMacExtras/index.html>`_ - Provides classes and functions specific to - macOS and iOS operating systems. - - `Qt Svg <PySide2/QtSvg/index.html>`_ - Provides classes for displaying the contents of SVG files. - * - `Qt UiTools <PySide2/QtUiTools/index.html>`_ - Provides classes to handle forms created with Qt Designer. - - `Qt Test <PySide2/QtTest/index.html>`_ - Provides classes for unit testing Qt applications and libraries. - * - `Qt Concurrent <PySide2/QtConcurrent/index.html>`_ - Provides high-level APIs that make it possible - to write multi-threaded programs without using low-level threading - primitives such as mutexes, read-write locks, wait conditions, or semaphores. - - `Qt AxContainer <PySide2/QtAxContainer/index.html>`_ - Provides QAxObject and QAxWidget which act as - containers for COM objects and ActiveX controls. - * - `Qt WebEngineCore <PySide2/QtWebEngineCore/index.html>`_ - Provides the core functionality to integrate web content - - `Qt WebEngineWidgets <PySide2/QtWebEngineWidgets/index.html>`_ - Provides widgets that can handle web content - * - `Qt WebChannel <PySide2/QtWebChannel/index.html>`_ - Enables peer-to-peer communication between a server and a client - (HTML/JavaScript or QML application). - - `Qt WebSockets <PySide2/QtWebSockets/index.html>`_ - Provides interfaces that enable Qt applications - to act as a server that can process WebSocket requests, or a client that - can consume data received from the server, or both. - * - `Qt Widgets <PySide2/QtWidgets/index.html>`_ - Extends Qt GUI with C++ widget functionality. - - `Qt WinExtras <PySide2/QtWinExtras/index.html>`_ - Provides classes and functions for using some Windows APIs in a Qt way. - * - `Qt X11Extras <PySide2/QtX11Extras/index.html>`_ - Provides information about the X display configuration. - - `Qt Xml <PySide2/QtXml/index.html>`_ - Provides C++ implementations of SAX and DOM. - * - `Qt XmlPatterns <PySide2/QtXmlPatterns/index.html>`_ - Provides support for XPath, XQuery, XSLTi, and XML Schema validation. - - `Qt 3D Core <PySide2/Qt3DCore/index.html>`_ - Contains functionality to support near-realtime simulation systems. - * - `Qt 3D Extras <PySide2/Qt3DExtras/index.html>`_ - Provides a set of prebuilt elements to help you get started with Qt 3D. - - `Qt 3D Input <PySide2/Qt3DInput/index.html>`_ - Provides classes for handling user input in applications using Qt 3D. - * - `Qt 3D Logic <PySide2/Qt3DLogic/index.html>`_ - Enables synchronizing frames with the Qt 3D backend. - - `Qt 3D Render <PySide2/Qt3DRender/index.html>`_ - Contains functionality to support 2D and 3D rendering using Qt 3D. - * - `Qt Positioning <PySide2/QtPositioning/index.html>`_ - Provides positioning information via QML and Python interfaces. - - `Qt Location <PySide2/QtLocation/index.html>`_ - Helps you create viable mapping solutions using the data available from some of the popular location services. - * - `Qt Sensors <PySide2/QtSensors/index.html>`_ - Provides access to sensor hardware via QML and Python interfaces and a motion gesture recognition API for devices. - - `Qt Scxml <PySide2/QtScxml/index.html>`_ - Provides classes to create and use state machines from SCXML files. +Basic modules +------------- + These are the main modules that will help you build a Widget based UI. + + `Qt Core <PySide2/QtCore/index.html>`_ + Provides core non-GUI functionality, like signal and slots, properties, base classes of item models, serialization, etc. + `Qt Gui <PySide2/QtGui/index.html>`_ + Extends QtCore with GUI functionality: Events, windows and screens, OpenGL and raster-based 2D painting, images. + `Qt Widgets <PySide2/QtWidgets/index.html>`_ + Ready to use Widgets for your application, including also graphical elements for your UI. + +QML and Qt Quick +---------------- + If you want to use the `Qml Language <https://doc.qt.io/qt-5/qmlapplications.html>`, these + modules will help you interact with it from Python. + + `Qt Qml <PySide2/QtQml/index.html>`_ + Base Python API to interact with the QML module. + `Qt Quick <PySide2/QtQuick/index.html>`_ + Provides classes for embedding Qt Quick in Qt applications. + `Qt QuickWidgets <PySide2/QtQuickWidgets/index.html>`_ + Provides the QQuickWidget class for embedding Qt Quick in widget-based applications. + +Data visualization +------------------ + + Charts, diagrams, animations: these modules provide a large amount + of classes that can help you include these elements in your UI. + + `Qt Charts <PySide2/QtCharts/index.html>`_ + Provides a set of easy to use chart components. + `Qt DataVisualization <PySide2/QtDataVisualization/index.html>`_ + Provides a way to visualize data in 3D as bar, scatter, and surface graphs. + +Multimedia +----------- + + Audio, video, and hardware interaction: check these modules if you are + looking for multimedia solutions. + + `Qt Multimedia <PySide2/QtMultimedia/index.html>`_ + Provides low-level multimedia functionality. + `Qt MultimediaWidgets <PySide2/QtMultimediaWidgets/index.html>`_ + Provides the widget-based multimedia API. + +WebEngine +--------- + + If your project is based on a browser or the features around web + based applications, these modules will help you to interact with them. + + `Qt WebEngineWidgets <PySide2/QtWebEngineWidgets/index.html>`_ + Provides widgets that can handle web content. + `Qt WebChannel <PySide2/QtWebChannel/index.html>`_ + Enables peer-to-peer communication between a server and a client + (HTML/JavaScript or QML application). + +All the modules +--------------- + + There are many other modules currently supported by |pymodname|, + here you can find a complete list of them. + + `Check all the modules <modules.html>`_ + Display a table with all the currently supported Qt modules. diff --git a/sources/pyside2/doc/modules.rst b/sources/pyside2/doc/modules.rst new file mode 100644 index 000000000..1d6564300 --- /dev/null +++ b/sources/pyside2/doc/modules.rst @@ -0,0 +1,94 @@ +Qt Modules +=========== + +.. list-table:: + :widths: 150, 150 + :align: left + + * - `Qt Core <PySide2/QtCore/index.html>`_ + Provides core non-GUI functionality. + - `Qt 3D Animation <PySide2/Qt3DAnimation/index.html>`_ + Provides basic elements required to animate 3D objects. + * - `Qt Gui <PySide2/QtGui/index.html>`_ + Extends QtCore with GUI functionality. + - `Qt Help <PySide2/QtHelp/index.html>`_ + Provides classes for integrating online documentation in applications. + * - `Qt Network <PySide2/QtNetwork/index.html>`_ + Offers classes that let you to write TCP/IP clients and servers. + - `Qt OpenGL <PySide2/QtOpenGL/index.html>`_ + Offers classes that make it easy to use OpenGL in Qt applications. + * - `Qt PrintSupport <PySide2/QtPrintSupport/index.html>`_ + Provides extensive cross-platform support for printing. + - `Qt Qml <PySide2/QtQml/index.html>`_ + Python API for Qt QML. + * - `Qt Charts <PySide2/QtCharts/index.html>`_ + Provides a set of easy to use chart components. + - `Qt Quick <PySide2/QtQuick/index.html>`_ + Provides classes for embedding Qt Quick in Qt applications. + * - `Qt DataVisualization <PySide2/QtDataVisualization/index.html>`_ + Provides a way to visualize data in 3D as bar, scatter, and surface graphs. + - `Qt QuickWidgets <PySide2/QtQuickWidgets/index.html>`_ + Provides the QQuickWidget class for embedding Qt Quick in widget-based applications. + * - `Qt TextToSpeech <PySide2/QtTextToSpeech/index.html>`_ + Provides API to access text-to-speech engines. + - `Qt Sql <PySide2/QtSql/index.html>`_ + Helps you provide seamless database integration to your Qt applications. + * - `Qt Multimedia <PySide2/QtMultimedia/index.html>`_ + Provides low-level multimedia functionality. + - `Qt MultimediaWidgets <PySide2/QtMultimediaWidgets/index.html>`_ + Provides the widget-based multimedia API. + * - `Qt MacExtras <PySide2/QtMacExtras/index.html>`_ + Provides classes and functions specific to + macOS and iOS operating systems. + - `Qt Svg <PySide2/QtSvg/index.html>`_ + Provides classes for displaying the contents of SVG files. + * - `Qt UiTools <PySide2/QtUiTools/index.html>`_ + Provides classes to handle forms created with Qt Designer. + - `Qt Test <PySide2/QtTest/index.html>`_ + Provides classes for unit testing Qt applications and libraries. + * - `Qt Concurrent <PySide2/QtConcurrent/index.html>`_ + Provides high-level APIs that make it possible + to write multi-threaded programs without using low-level threading + primitives such as mutexes, read-write locks, wait conditions, or semaphores. + - `Qt AxContainer <PySide2/QtAxContainer/index.html>`_ + Provides QAxObject and QAxWidget which act as + containers for COM objects and ActiveX controls. + * - `Qt WebEngineCore <PySide2/QtWebEngineCore/index.html>`_ + Provides the core functionality to integrate web content. + - `Qt WebEngineWidgets <PySide2/QtWebEngineWidgets/index.html>`_ + Provides widgets that can handle web content. + * - `Qt WebChannel <PySide2/QtWebChannel/index.html>`_ + Enables peer-to-peer communication between a server and a client + (HTML/JavaScript or QML application). + - `Qt WebSockets <PySide2/QtWebSockets/index.html>`_ + Provides interfaces that enable Qt applications + to act as a server that can process WebSocket requests, or a client that + can consume data received from the server, or both. + * - `Qt Widgets <PySide2/QtWidgets/index.html>`_ + Extends Qt GUI with C++ widget functionality. + - `Qt WinExtras <PySide2/QtWinExtras/index.html>`_ + Provides classes and functions for using some Windows APIs in a Qt way. + * - `Qt X11Extras <PySide2/QtX11Extras/index.html>`_ + Provides information about the X display configuration. + - `Qt Xml <PySide2/QtXml/index.html>`_ + Provides C++ implementations of SAX and DOM. + * - `Qt XmlPatterns <PySide2/QtXmlPatterns/index.html>`_ + Provides support for XPath, XQuery, XSLTi, and XML Schema validation. + - `Qt 3D Core <PySide2/Qt3DCore/index.html>`_ + Contains functionality to support near-realtime simulation systems. + * - `Qt 3D Extras <PySide2/Qt3DExtras/index.html>`_ + Provides a set of prebuilt elements to help you get started with Qt 3D. + - `Qt 3D Input <PySide2/Qt3DInput/index.html>`_ + Provides classes for handling user input in applications using Qt 3D. + * - `Qt 3D Logic <PySide2/Qt3DLogic/index.html>`_ + Enables synchronizing frames with the Qt 3D backend. + - `Qt 3D Render <PySide2/Qt3DRender/index.html>`_ + Contains functionality to support 2D and 3D rendering using Qt 3D. + * - `Qt Positioning <PySide2/QtPositioning/index.html>`_ + Provides positioning information via QML and Python interfaces. + - `Qt Location <PySide2/QtLocation/index.html>`_ + Helps you create viable mapping solutions using the data available from some of the popular location services. + * - `Qt Sensors <PySide2/QtSensors/index.html>`_ + Provides access to sensor hardware via QML and Python interfaces and a motion gesture recognition API for devices. + - `Qt Scxml <PySide2/QtScxml/index.html>`_ + Provides classes to create and use state machines from SCXML files. diff --git a/sources/pyside2/doc/overview.rst b/sources/pyside2/doc/overview.rst new file mode 100644 index 000000000..e8a8ace00 --- /dev/null +++ b/sources/pyside2/doc/overview.rst @@ -0,0 +1,42 @@ +Overview +========= + +The |project| project aims to provide a complete port of the PySide module to Qt 5. +The development started on GitHub in May 2015. The project managed to port Pyside to +Qt 5.3, 5. 4 & 5.5. + +The `PySide2` module was released mid June 2018 as a Technical Preview (supporting Qt 5.11), +and it has been fully supported since Qt 5.12. + +|project| is available under LGPLv3/GPLv2 and commercial license for the following platforms: + ++-------------+--------+--------+--------+--------+---------+---------+ +| | Linux | macOS | Windows | ++=============+========+========+========+========+=========+=========+ +| | 32bit | 64bit | 32bit | 64bit | 32bit | 64bit | ++-------------+--------+--------+--------+--------+---------+---------+ +| Python 2.7 | No (*) | Yes | No (*) | Yes | No (**) | No (**) | ++-------------+--------+--------+--------+--------+---------+---------+ +| Python 3.5+ | No (*) | Yes | No (*) | Yes | Yes | Yes | ++-------------+--------+--------+--------+--------+---------+---------+ + + * (*): `No Qt release <https://wiki.qt.io/Qt_5.12_Tools_and_Versions#Software_configurations_for_Qt_5.12.0>`_ + * (**): `MSVC issue with Python 2.7 and Qt <https://wiki.qt.io/Qt_for_Python/Considerations#Missing_Windows_.2F_Python_2.7_release>`_ + + +What does PySide2 look like? +---------------------------- + +A simple Hello World example in PySide2 looks like this: + +:: + + import sys + from PySide2.QtWidgets import QApplication, QLabel + + + if __name__ == "__main__": + app = QApplication(sys.argv) + label = QLabel("Hello World") + label.show() + sys.exit(app.exec_()) diff --git a/sources/pyside2/tests/registry/existence_test.py b/sources/pyside2/tests/registry/existence_test.py index 62795f232..fd81901b4 100644 --- a/sources/pyside2/tests/registry/existence_test.py +++ b/sources/pyside2/tests/registry/existence_test.py @@ -1,6 +1,6 @@ ############################################################################# ## -## Copyright (C) 2017 The Qt Company Ltd. +## Copyright (C) 2019 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qt for Python. @@ -41,8 +41,29 @@ from __future__ import print_function, absolute_import """ existence_test.py +----------------- A test that checks all function signatures if they still exist. + +Definition of the rules used: +============================= + +Any entry +--------- + + Exists in file Exists in Binary Result + + + ok + + - error + - + ok + +List entry +---------- + + Arity in file Arity in Binary Result + n n ok + n < n error + n > n ok + """ import os @@ -87,16 +108,6 @@ if have_refmodule and not hasattr(sig_exists, "dict"): os.unlink(effectiveRefPath) have_refmodule = False -def formatSignatures(signatures): - result = '' - for s in signatures: - result += ' ({})'.format(','.join(s)) - return result - -def msgMultiSignatureCount(key, actual, expected): - return "multi-signature count mismatch for '{}'. Actual {} [{}] vs. expected {} [{}]')".format(key, - len(actual), formatSignatures(actual), - len(expected), formatSignatures(expected)) @unittest.skipIf(not have_refmodule, "not activated for this platform or version") @@ -107,38 +118,93 @@ class TestSignaturesExists(unittest.TestCase): file. Simply run init_platform.py and add the generated file to the repository. """ + + @staticmethod + def _do_the_test(found_sigs): + + def multi_signature_msg(key, actual, expect): + len_act = len(actual) if type(actual) is list else 1 + len_exp = len(expect) if type(expect) is list else 1 + return ("multi-signature count mismatch for '{key}'. " + "Actual {len_act} {actual} vs. expected {len_exp} {expect}')" + .format(**locals())) + + for key, value in sig_exists.dict.items(): + name = key.rsplit(".", 1)[-1] + if name in ("next", "__next__"): # ignore problematic cases + continue + if key not in found_sigs: + warn("missing key: '{}'".format(key)) + else: + found_val = found_sigs[key] + if type(value) is list and ( + type(found_val) is tuple or + len(found_val) < len(value)): + # We check that nothing got lost. But it is ok when an older + # registry file does not know all variants, yet! + warn(multi_signature_msg(key, found_val, value)) + def test_signatures(self): found_sigs = enum_all() with isolate_warnings(): - for key, value in sig_exists.dict.items(): - name = key.rsplit(".", 1)[-1] - if name in ("next", "__next__"): # ignore problematic cases - continue - if key not in found_sigs: - warn("missing key: '{}'".format(key)) - elif isinstance(value, list) and len(value) > len(found_sigs[key]): - # We check that nothing got lost. But it is ok when an older - # registry file does not have all variants, yet! - warn(msgMultiSignatureCount(key, found_sigs[key], value)) + self._do_the_test(found_sigs) if is_ci and check_warnings(): raise RuntimeError("There are errors, see above.") def test_error_is_raised(self): found_sigs = enum_all() - # make sure that errors are actually raised - found_sigs.pop(list(found_sigs.keys())[42]) + # Make sure that errors are actually raised. + search = list(found_sigs.keys()) + pos = 42 # arbitrary and historycal, could be 0 as well + + # We try all variants: + while type(found_sigs[search[pos]]) is not tuple: + pos += 1 + tuple_key = search[pos] + while type(found_sigs[search[pos]]) is not list: + pos += 1 + list_key = search[pos] + + test_sigs = found_sigs.copy() + test_sigs.pop(tuple_key) with isolate_warnings(), suppress_warnings(): - for key, value in sig_exists.dict.items(): - name = key.rsplit(".", 1)[-1] - if name in ("next", "__next__"): # ignore problematic cases - continue - if key not in found_sigs: - warn("missing key: '{}'".format(key)) - elif isinstance(value, list) and len(value) > len(found_sigs[key]): - # We check that nothing got lost. But it is ok when an older - # registry file does not have all variants, yet! - warn(msgMultiSignatureCount(key, found_sigs[key], value)) - self.assertTrue(check_warnings()) + self._do_the_test(test_sigs) + self.assertTrue(check_warnings(), "you warn about too few entries") + + test_sigs = found_sigs.copy() + test_sigs["whatnot"] = ("nothing", "real") + with isolate_warnings(), suppress_warnings(): + self._do_the_test(test_sigs) + self.assertFalse(check_warnings(), "you ignore too many entries") + + test_sigs = found_sigs.copy() + repl = test_sigs[list_key] + repl.pop(0) + test_sigs[list_key] = repl + with isolate_warnings(), suppress_warnings(): + self._do_the_test(test_sigs) + # An arity that is now missing is an error. + self.assertTrue(check_warnings(), "you warn when arity got smaller") + + test_sigs = found_sigs.copy() + repl = test_sigs[list_key] + repl = repl[0] + assert type(repl) is tuple + test_sigs[list_key] = repl + with isolate_warnings(), suppress_warnings(): + self._do_the_test(test_sigs) + # An arity that is now missing is an error. + self.assertTrue(check_warnings(), "you warn when list degraded to tuple") + + test_sigs = found_sigs.copy() + repl = test_sigs[list_key] + repl = repl + repl + test_sigs[list_key] = repl + with isolate_warnings(), suppress_warnings(): + self._do_the_test(test_sigs) + # More arities are ignored, because we might test an older version. + self.assertFalse(check_warnings(), "you ignore when arity got bigger") + tested_versions = (5, 6), (5, 9), (5, 11), (5, 12) diff --git a/sources/pyside2/tests/registry/util.py b/sources/pyside2/tests/registry/util.py index b2a246473..415b8aa45 100644 --- a/sources/pyside2/tests/registry/util.py +++ b/sources/pyside2/tests/registry/util.py @@ -86,7 +86,7 @@ def check_warnings(): # XXX We need to filter warnings for Python 2. # This should be avoided by renaming the duplicate folders. for k in reg: - if type(k) == tuple and re.match(ignore_re, k[0]): + if type(k) is tuple and re.match(ignore_re, k[0]): continue return True return False diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 0b11b1666..e62a2a78a 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -669,7 +669,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) checkFunctionModifications(); // sort all classes topologically - m_metaClasses = classesTopologicalSorted(); + m_metaClasses = classesTopologicalSorted(m_metaClasses); for (AbstractMetaClass* cls : qAsConst(m_metaClasses)) { // setupEquals(cls); @@ -681,7 +681,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!cls->typeEntry()->codeGeneration() || cls->innerClasses().size() < 2) continue; - cls->setInnerClasses(classesTopologicalSorted(cls)); + cls->setInnerClasses(classesTopologicalSorted(cls->innerClasses())); } dumpLog(); @@ -3085,27 +3085,37 @@ void AbstractMetaBuilderPrivate::dumpLog() const writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_fields.log"), m_rejectedFields); } -AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClass *cppClass, - const Dependencies &additionalDependencies) const +using ClassIndexHash = QHash<AbstractMetaClass *, int>; + +static ClassIndexHash::ConstIterator findByTypeEntry(const ClassIndexHash &map, + const TypeEntry *typeEntry) { - QLinkedList<int> unmappedResult; - QHash<QString, int> map; - QHash<int, AbstractMetaClass*> reverseMap; + auto it = map.cbegin(); + for (auto end = map.cend(); it != end; ++it) { + if (it.key()->typeEntry() == typeEntry) + break; + } + return it; +} - const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses; +AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassList &classList, + const Dependencies &additionalDependencies) const +{ + ClassIndexHash map; + QHash<int, AbstractMetaClass *> reverseMap; int i = 0; for (AbstractMetaClass *clazz : classList) { - if (map.contains(clazz->qualifiedCppName())) + if (map.contains(clazz)) continue; - map[clazz->qualifiedCppName()] = i; - reverseMap[i] = clazz; + map.insert(clazz, i); + reverseMap.insert(i, clazz); i++; } Graph graph(map.count()); - for (const Dependency &dep : additionalDependencies) { + for (const auto &dep : additionalDependencies) { const int parentIndex = map.value(dep.parent, -1); const int childIndex = map.value(dep.child, -1); if (parentIndex >= 0 && childIndex >= 0) { @@ -3113,18 +3123,17 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } else { qCWarning(lcShiboken).noquote().nospace() << "AbstractMetaBuilder::classesTopologicalSorted(): Invalid additional dependency: " - << dep.child << " -> " << dep.parent << '.'; + << dep.child->name() << " -> " << dep.parent->name() << '.'; } } - // TODO choose a better name to these regexs - static const QRegularExpression regex1(QStringLiteral("\\(.*\\)")); - Q_ASSERT(regex1.isValid()); - static const QRegularExpression regex2(QStringLiteral("::.*")); - Q_ASSERT(regex2.isValid()); for (AbstractMetaClass *clazz : classList) { - if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName())) - graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]); + const int classIndex = map.value(clazz); + if (auto enclosing = clazz->enclosingClass()) { + const auto enclosingIt = map.constFind(const_cast< AbstractMetaClass *>(enclosing)); + if (enclosingIt!= map.cend()) + graph.addEdge(enclosingIt.value(), classIndex); + } const AbstractMetaClassList &bases = getBaseClasses(clazz); for (AbstractMetaClass *baseClass : bases) { @@ -3132,58 +3141,39 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const if (clazz->baseClass() == baseClass) clazz->setBaseClass(baseClass); - if (map.contains(baseClass->qualifiedCppName())) - graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]); + const auto baseIt = map.constFind(baseClass); + if (baseIt!= map.cend()) + graph.addEdge(baseIt.value(), classIndex); } const AbstractMetaFunctionList &functions = clazz->functions(); for (AbstractMetaFunction *func : functions) { const AbstractMetaArgumentList &arguments = func->arguments(); for (AbstractMetaArgument *arg : arguments) { - // check methods with default args - QString defaultExpression = arg->originalDefaultValueExpression(); - if (!defaultExpression.isEmpty()) { - if (defaultExpression == QLatin1String("0") && arg->type()->isValue()) - defaultExpression = arg->type()->name(); - - defaultExpression.remove(regex1); - defaultExpression.remove(regex2); - } - if (!defaultExpression.isEmpty()) { - QString exprClassName = clazz->qualifiedCppName() + colonColon() + defaultExpression; - if (!map.contains(exprClassName)) { - bool found = false; - for (AbstractMetaClass *baseClass : bases) { - exprClassName = baseClass->qualifiedCppName() + colonColon() + defaultExpression; - if (map.contains(exprClassName)) { - found = true; - break; - } - } - if (!found) { - if (map.contains(defaultExpression)) - exprClassName = defaultExpression; - else - exprClassName.clear(); - } + // Check methods with default args: If a class is instantiated by value, + // ("QString s = QString()"), add a dependency. + if (!arg->originalDefaultValueExpression().isEmpty() + && arg->type()->isValue()) { + auto typeEntry = arg->type()->typeEntry(); + if (typeEntry->isComplex() && typeEntry != clazz->typeEntry()) { + auto ait = findByTypeEntry(map, typeEntry); + if (ait != map.cend() && ait.key()->enclosingClass() != clazz) + graph.addEdge(ait.value(), classIndex); } - if (!exprClassName.isEmpty() && exprClassName != clazz->qualifiedCppName()) - graph.addEdge(map[exprClassName], map[clazz->qualifiedCppName()]); } } } } AbstractMetaClassList result; - unmappedResult = graph.topologicalSort(); + const auto unmappedResult = graph.topologicalSort(); if (unmappedResult.isEmpty() && graph.nodeCount()) { - QTemporaryFile tempFile; + QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/cyclic_depXXXXXX.dot")); tempFile.setAutoRemove(false); tempFile.open(); QHash<int, QString> hash; - QHash<QString, int>::iterator it = map.begin(); - for (; it != map.end(); ++it) - hash[it.value()] = it.key(); + for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) + hash.insert(it.value(), it.key()->qualifiedCppName()); graph.dumpDot(hash, tempFile.fileName()); qCWarning(lcShiboken).noquote().nospace() << "Cyclic dependency found! Graph can be found at " @@ -3199,10 +3189,10 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const return result; } -AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClass *cppClass, +AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClassList &classList, const Dependencies &additionalDependencies) const { - return d->classesTopologicalSorted(cppClass, additionalDependencies); + return d->classesTopologicalSorted(classList, additionalDependencies); } AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractMetaArgumentList &list) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index 7e5c1fc79..ed89060ac 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -68,12 +68,10 @@ public: AbstractMetaEnum *findEnum(const TypeEntry *typeEntry) const; /** - * Sorts a list of classes topologically, if an AbstractMetaClass object - * is passed the list of classes will be its inner classes, otherwise - * the list will be the module global classes. + * Sorts a list of classes topologically. * \return a list of classes sorted topologically */ - AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, + AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClassList &classList, const Dependencies &additionalDependencies = Dependencies()) const; bool build(const QByteArrayList &arguments, diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 185dd0e30..d8203a586 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -52,7 +52,7 @@ public: void traverseDom(const FileModelItem &dom); void dumpLog() const; - AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, + AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClassList &classList, const Dependencies &additionalDependencies = Dependencies()) const; ScopeModelItem popScope() { return m_scopes.takeLast(); } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 9d36706ac..0c652a39a 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -95,6 +95,8 @@ public: return m_format; } + void setFormat(Format f) { m_format = f; } + private: QString m_data; Format m_format = Documentation::Native; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index 7d2ce250e..e301d891f 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -153,7 +153,7 @@ AbstractMetaClassList ApiExtractor::smartPointers() const AbstractMetaClassList ApiExtractor::classesTopologicalSorted(const Dependencies &additionalDependencies) const { Q_ASSERT(m_builder); - return m_builder->classesTopologicalSorted(Q_NULLPTR, additionalDependencies); + return m_builder->classesTopologicalSorted(m_builder->classes(), additionalDependencies); } PrimitiveTypeEntryList ApiExtractor::primitiveTypes() const diff --git a/sources/shiboken2/ApiExtractor/dependency.h b/sources/shiboken2/ApiExtractor/dependency.h index 97ae32df9..d563e9094 100644 --- a/sources/shiboken2/ApiExtractor/dependency.h +++ b/sources/shiboken2/ApiExtractor/dependency.h @@ -29,13 +29,17 @@ #ifndef DEPENDENCY_H #define DEPENDENCY_H -#include <QtCore/QString> #include <QtCore/QVector> +#include <utility> + // Dependencies for topologically sorting classes + +class AbstractMetaClass; + struct Dependency { - QString parent; - QString child; + AbstractMetaClass *parent; + AbstractMetaClass *child; }; typedef QVector<Dependency> Dependencies; diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg Binary files differdeleted file mode 100644 index 2a1fbe7a1..000000000 --- a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg +++ /dev/null diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png Binary files differindex 076c1057c..3a2f2bd17 100644 --- a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png +++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp index 65f33e373..c2ac81e6c 100644 --- a/sources/shiboken2/ApiExtractor/graph.cpp +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -29,7 +29,6 @@ #include "graph.h" #include <QVector> #include <QDebug> -#include <QLinkedList> #include <QSet> #include <iterator> #include <algorithm> @@ -48,7 +47,7 @@ struct Graph::GraphPrivate { } - void dfsVisit(int node, QLinkedList<int>& result, QVector<Color>& colors) const + void dfsVisit(int node, Graph::Indexes &result, QVector<Color> &colors) const { colors[node] = GRAY; EdgeIterator it = edges[node].begin(); @@ -59,7 +58,7 @@ struct Graph::GraphPrivate return; } colors[node] = BLACK; - result.push_front(node); + result.append(node); } }; @@ -77,10 +76,12 @@ int Graph::nodeCount() const return m_d->edges.size(); } -QLinkedList<int> Graph::topologicalSort() const +Graph::Indexes Graph::topologicalSort() const { - int nodeCount = Graph::nodeCount(); - QLinkedList<int> result; + const int nodeCount = Graph::nodeCount(); + Indexes result; + result.reserve(nodeCount); + QVector<GraphPrivate::Color> colors(nodeCount, GraphPrivate::WHITE); for (int i = 0; i < nodeCount; ++i) { @@ -88,9 +89,10 @@ QLinkedList<int> Graph::topologicalSort() const m_d->dfsVisit(i, result, colors); } - // Not a DAG! - if (result.size() != nodeCount) - return QLinkedList<int>(); + if (result.size() == nodeCount) + std::reverse(result.begin(), result.end()); + else + result.clear(); // Not a DAG! return result; } diff --git a/sources/shiboken2/ApiExtractor/graph.h b/sources/shiboken2/ApiExtractor/graph.h index 879ac97e4..043a182b5 100644 --- a/sources/shiboken2/ApiExtractor/graph.h +++ b/sources/shiboken2/ApiExtractor/graph.h @@ -29,7 +29,7 @@ #ifndef GRAPH_H #define GRAPH_H -#include <QLinkedList> +#include <QVector> #include <QHash> #include <QString> @@ -37,6 +37,8 @@ class Graph { public: + using Indexes = QVector<int>; + /// Create a new graph with \p numNodes nodes. Graph(int numNodes); ~Graph(); @@ -60,9 +62,10 @@ public: /** * Topologically sort this graph. - * \return A collection with all nodes topologically sorted or an empty collection if a ciclic dependency was found. + * \return A collection with all nodes topologically sorted or an empty collection if a cyclic + * dependency was found. */ - QLinkedList<int> topologicalSort() const; + Indexes topologicalSort() const; private: struct GraphPrivate; diff --git a/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp index 216101215..7e5664842 100644 --- a/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp @@ -73,8 +73,9 @@ void TestExtraInclude::testGlobalExtraIncludes() QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("A"))); TypeDatabase* td = TypeDatabase::instance(); - TypeEntry* module = td->findType(QLatin1String("Foo")); + const TypeSystemTypeEntry *module = td->defaultTypeSystemType(); QVERIFY(module); + QCOMPARE(module->name(), QLatin1String("Foo")); QVector<Include> includes = module->extraIncludes(); QCOMPARE(includes.count(), 2); diff --git a/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp index 8962f83ff..2d1692ee9 100644 --- a/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp @@ -74,7 +74,9 @@ void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() AbstractMetaClassList classes = builder->classes(); QVERIFY(classes.isEmpty()); - TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); + const TypeSystemTypeEntry *module = TypeDatabase::instance()->defaultTypeSystemType(); + QVERIFY(module); + QCOMPARE(module->name(), QLatin1String("Foo")); QVERIFY(module); QCOMPARE(module->codeSnips().count(), 1); QString code = module->codeSnips().first().code().trimmed(); diff --git a/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp b/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp index 9d7729513..c59fa8c3d 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp @@ -33,23 +33,22 @@ void TestTopoSort::testTopoSort() { - QLinkedList<int> result; { Graph g(3); g.addEdge(1, 2); g.addEdge(0, 1); - result = g.topologicalSort(); + const auto result = g.topologicalSort(); QCOMPARE(result.size(), 3); - QLinkedList<int>::iterator it = result.begin(); + auto it = result.begin(); QCOMPARE(*it, 0); QCOMPARE(*(++it), 1); QCOMPARE(*(++it), 2); } { Graph g(2); - result = g.topologicalSort(); + const auto result = g.topologicalSort(); QCOMPARE(result.size(), 2); - QLinkedList<int>::iterator it = result.begin(); + auto it = result.begin(); QCOMPARE(*it, 1); QCOMPARE(*(++it), 0); } @@ -61,7 +60,7 @@ void TestTopoSort::testCiclicGraph() g.addEdge(0, 1); g.addEdge(1, 2); g.addEdge(2, 0); - QLinkedList<int> result = g.topologicalSort(); + const auto result = g.topologicalSort(); QVERIFY(result.isEmpty()); } diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index c0999e7ab..4ce2790f5 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -182,16 +182,31 @@ FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const return 0; } +void TypeDatabase::addTypeSystemType(const TypeSystemTypeEntry *e) +{ + m_typeSystemEntries.append(e); +} + const TypeSystemTypeEntry *TypeDatabase::findTypeSystemType(const QString &name) const { - const auto entries = findTypes(name); - for (const TypeEntry *entry : entries) { - if (entry->type() == TypeEntry::TypeSystemType) - return static_cast<const TypeSystemTypeEntry *>(entry); + for (auto entry : m_typeSystemEntries) { + if (entry->name() == name) + return entry; } return nullptr; } +const TypeSystemTypeEntry *TypeDatabase::defaultTypeSystemType() const +{ + return m_typeSystemEntries.value(0, nullptr); +} + +QString TypeDatabase::defaultPackageName() const +{ + Q_ASSERT(!m_typeSystemEntries.isEmpty()); + return m_typeSystemEntries.constFirst()->name(); +} + TypeEntry* TypeDatabase::findType(const QString& name) const { const auto entries = findTypes(name); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index 247d74362..0040364bf 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -91,6 +91,8 @@ public: ContainerTypeEntry* findContainerType(const QString& name) const; FunctionTypeEntry* findFunctionType(const QString& name) const; const TypeSystemTypeEntry *findTypeSystemType(const QString &name) const; + const TypeSystemTypeEntry *defaultTypeSystemType() const; + QString defaultPackageName() const; TypeEntry* findType(const QString& name) const; @@ -115,6 +117,7 @@ public: QString *reason = nullptr) const; bool addType(TypeEntry* e, QString *errorMessage = nullptr); + void addTypeSystemType(const TypeSystemTypeEntry *e); FlagsTypeEntry* findFlagsType(const QString& name) const; void addFlagsType(FlagsTypeEntry* fte); @@ -172,6 +175,7 @@ private: TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; QVector<QRegularExpression> m_suppressedWarnings; + QVector<const TypeSystemTypeEntry *> m_typeSystemEntries; // maintain order, default is first. AddedFunctionList m_globalUserFunctions; FunctionModificationList m_functionMods; diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 204253777..ad97e40ee 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -1509,7 +1509,8 @@ TypeSystemTypeEntry *Handler::parseRootElement(const QXmlStreamReader &, TypeSystemTypeEntry *moduleEntry = const_cast<TypeSystemTypeEntry *>(m_database->findTypeSystemType(m_defaultPackage)); - if (!moduleEntry) + const bool add = moduleEntry == nullptr; + if (add) moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since); moduleEntry->setCodeGeneration(m_generate); @@ -1517,8 +1518,8 @@ TypeSystemTypeEntry *Handler::parseRootElement(const QXmlStreamReader &, m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty()) TypeDatabase::instance()->addRequiredTargetImport(m_defaultPackage); - if (!moduleEntry->qualifiedCppName().isEmpty()) - m_database->addType(moduleEntry); + if (add) + m_database->addTypeSystemType(moduleEntry); return moduleEntry; } diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png Binary files differindex 076c1057c..3a2f2bd17 100644 --- a/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png +++ b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index ec227bd83..154a16ed3 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -176,19 +176,13 @@ Generator::~Generator() bool Generator::setup(const ApiExtractor& extractor) { m_d->apiextractor = &extractor; - const auto &allEntries = TypeDatabase::instance()->entries(); - TypeEntry* entryFound = 0; - for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { - TypeEntry *entry = it.value(); - if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) { - entryFound = entry; - break; - } - } - if (entryFound) - m_d->packageName = entryFound->name(); - else + const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType(); + if (!moduleEntry || !moduleEntry->generateCode()) { qCWarning(lcShiboken) << "Couldn't find the package name!!"; + return false; + } + + m_d->packageName = moduleEntry->name(); collectInstantiatedContainersAndSmartPointers(); diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 9410bc158..05729f4b5 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -52,6 +52,8 @@ static inline QString nameAttribute() { return QStringLiteral("name"); } static inline QString titleAttribute() { return QStringLiteral("title"); } static inline QString fullTitleAttribute() { return QStringLiteral("fulltitle"); } static inline QString briefAttribute() { return QStringLiteral("brief"); } +static inline QString briefStartElement() { return QStringLiteral("<brief>"); } +static inline QString briefEndElement() { return QStringLiteral("</brief>"); } static inline QString none() { return QStringLiteral("None"); } @@ -336,6 +338,7 @@ QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, cons m_handlerMap.insert(QLatin1String("code"), &QtXmlToSphinx::handleCodeTag); m_handlerMap.insert(QLatin1String("badcode"), &QtXmlToSphinx::handleCodeTag); m_handlerMap.insert(QLatin1String("legalese"), &QtXmlToSphinx::handleCodeTag); + m_handlerMap.insert(QLatin1String("rst"), &QtXmlToSphinx::handleRstPassTroughTag); m_handlerMap.insert(QLatin1String("section"), &QtXmlToSphinx::handleAnchorTag); m_handlerMap.insert(QLatin1String("quotefile"), &QtXmlToSphinx::handleQuoteFileTag); @@ -1274,6 +1277,12 @@ void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader) } } +void QtXmlToSphinx::handleRstPassTroughTag(QXmlStreamReader& reader) +{ + if (reader.tokenType() == QXmlStreamReader::Characters) + m_output << reader.text(); +} + void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) { QXmlStreamReader::TokenType token = reader.tokenType(); @@ -1578,6 +1587,30 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl s << classes.join(QLatin1String(", ")) << endl << endl; } +// Extract the <brief> section from a WebXML (class) documentation and remove it +// from the source. +static bool extractBrief(Documentation *sourceDoc, Documentation *brief) +{ + if (sourceDoc->format() != Documentation::Native) + return false; + QString value = sourceDoc->value(); + const int briefStart = value.indexOf(briefStartElement()); + if (briefStart < 0) + return false; + const int briefEnd = value.indexOf(briefEndElement(), briefStart + briefStartElement().size()); + if (briefEnd < briefStart) + return false; + const int briefLength = briefEnd + briefEndElement().size() - briefStart; + brief->setFormat(Documentation::Native); + QString briefValue = value.mid(briefStart, briefLength); + briefValue.insert(briefValue.size() - briefEndElement().size(), + QLatin1String("<rst> More_...</rst>")); + brief->setValue(briefValue); + value.remove(briefStart, briefLength); + sourceDoc->setValue(value); + return true; +} + void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) { AbstractMetaClass *metaClass = classContext.metaClass(); @@ -1595,6 +1628,11 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex s << className << endl; s << Pad('*', className.count()) << endl << endl; + auto documentation = metaClass->documentation(); + Documentation brief; + if (extractBrief(&documentation, &brief)) + writeFormattedText(s, brief, metaClass); + s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << endl << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future... @@ -1615,11 +1653,12 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex s << endl << "Detailed Description\n" - "--------------------\n\n"; + "--------------------\n\n" + << ".. _More:\n"; writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, 0); if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, 0)) - writeFormattedText(s, metaClass->documentation(), metaClass); + writeFormattedText(s, documentation, metaClass); if (!metaClass->isNamespace()) writeConstructors(s, metaClass); diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index 43345716d..21afd0f49 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -150,6 +150,7 @@ private: void handleUnknownTag(QXmlStreamReader& reader); void handleUselessTag(QXmlStreamReader& reader); void handleAnchorTag(QXmlStreamReader& reader); + void handleRstPassTroughTag(QXmlStreamReader& reader); LinkContext *handleLinkStart(const QString &type, QString ref) const; void handleLinkText(LinkContext *linkContext, const QString &linktext) const; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index be9d426b5..039a2928b 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -4894,18 +4894,20 @@ void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnu s << '}' << endl << endl; } -QString CppGenerator::getInitFunctionName(GeneratorContext &context) const +QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const { - QString initFunctionName; - if (!context.forSmartPointer()) { - initFunctionName = context.metaClass()->qualifiedCppName(); - initFunctionName.replace(QLatin1String("::"), QLatin1String("_")); - } else { - initFunctionName = getFilteredCppSignatureString(context.preciseType()->cppSignature()); - } + QString initFunctionName = metaClass->qualifiedCppName(); + initFunctionName.replace(QLatin1String("::"), QLatin1String("_")); return initFunctionName; } +QString CppGenerator::getInitFunctionName(GeneratorContext &context) const +{ + return !context.forSmartPointer() + ? getSimpleClassInitFunctionName(context.metaClass()) + : getFilteredCppSignatureString(context.preciseType()->cppSignature()); +} + void CppGenerator::writeClassRegister(QTextStream &s, const AbstractMetaClass *metaClass, GeneratorContext &classContext, @@ -5428,12 +5430,13 @@ bool CppGenerator::finishGeneration() //We need move QMetaObject register before QObject Dependencies additionalDependencies; const AbstractMetaClassList &allClasses = classes(); - if (AbstractMetaClass::findClass(allClasses, qObjectClassName()) != Q_NULLPTR - && AbstractMetaClass::findClass(allClasses, qMetaObjectClassName()) != Q_NULLPTR) { - Dependency dependency; - dependency.parent = qMetaObjectClassName(); - dependency.child = qObjectClassName(); - additionalDependencies.append(dependency); + if (auto qObjectClass = AbstractMetaClass::findClass(allClasses, qObjectClassName())) { + if (auto qMetaObjectClass = AbstractMetaClass::findClass(allClasses, qMetaObjectClassName())) { + Dependency dependency; + dependency.parent = qMetaObjectClass; + dependency.child = qObjectClass; + additionalDependencies.append(dependency); + } } const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); @@ -5441,15 +5444,19 @@ bool CppGenerator::finishGeneration() if (!shouldGenerate(cls)) continue; - s_classInitDecl << "void init_" << cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")) << "(PyObject* module);" << endl; + const QString initFunctionName = QLatin1String("init_") + getSimpleClassInitFunctionName(cls); - QString defineStr = QLatin1String("init_") + cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")); + s_classInitDecl << "void " << initFunctionName << "(PyObject* module);" << endl; - if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) - defineStr += QLatin1String("(reinterpret_cast<PyTypeObject *>(") + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) + QLatin1String(")->tp_dict);"); - else - defineStr += QLatin1String("(module);"); - s_classPythonDefines << INDENT << defineStr << 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);"; + } + s_classPythonDefines << endl; } // Initialize smart pointer types. diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index 3035fad34..d2e04dba2 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -229,6 +229,7 @@ private: GeneratorContext &context, int maxArgs = 0); QString getInitFunctionName(GeneratorContext &context) const; + QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const; void writeClassRegister(QTextStream &s, const AbstractMetaClass *metaClass, diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index 6a85bf7ef..9f0ac51e5 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -426,7 +426,7 @@ void OverloadData::sortNextOverloads() } // sort the overloads topologically based on the dependency graph. - const QLinkedList<int> unmappedResult = graph.topologicalSort(); + const auto unmappedResult = graph.topologicalSort(); if (unmappedResult.isEmpty()) { QString funcName = referenceFunction()->name(); if (referenceFunction()->ownerClass()) |