pax_global_header 0000666 0000000 0000000 00000000064 13766170131 0014517 g ustar 00root root 0000000 0000000 52 comment=2b1d8a96882276884e9e641b75b1e6b6edea0a35
.gitattributes 0000664 0000000 0000000 00000000640 13766170131 0013756 0 ustar 00root root 0000000 0000000 # Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
*.py text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary .gitignore 0000664 0000000 0000000 00000003510 13766170131 0013052 0 ustar 00root root 0000000 0000000 ## PySide2
/pyside*_build
/pyside*_install
/PySide
/PySide-*.*.*
/SciTE.*
/pysideuic
distribute-*.egg
distribute-*.tar.gz
explore2
build_history/2*
*.qdocconf
*.qdocconf.in
*.egg-info
*.pyc
## C++
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
## Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
#dist/ # we place the changelogs here
downloads/
eggs/
.eggs/
/lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Translations
*.mo
*.pot
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don’t work, or not
# install all needed dependencies.
#Pipfile.lock
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
## CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
#Testing Conflicts with the testing directory
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
.gitmodules 0000664 0000000 0000000 00000000135 13766170131 0013237 0 ustar 00root root 0000000 0000000 [submodule "sources/pyside2-tools"]
path = sources/pyside2-tools
url = ../pyside-tools.git
.travis.yml 0000664 0000000 0000000 00000000641 13766170131 0013175 0 ustar 00root root 0000000 0000000 language: python
dist: trusty
python:
- "2.7"
- "3.5"
before_install:
- sudo add-apt-repository ppa:beineri/opt-qt551-trusty -y
- sudo apt-get update
install:
- sudo apt-get install qt55-meta-full -y
script:
- source /opt/qt55/bin/qt55-env.sh
- python setup.py install --jobs=2 --build-tests # --openssl=/path/to/openssl/bin
# how do we separate the build step and the tests, to see both as a result?
CMakeLists.txt 0000664 0000000 0000000 00000001403 13766170131 0013621 0 ustar 00root root 0000000 0000000 cmake_minimum_required(VERSION 3.1)
cmake_policy(VERSION 3.1)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build Type")
project(pyside2_super_project)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed.")
endif()
# Used to prevent overriding message function in both shiboken2 and pyside2.
set(is_pyside2_superproject_build 1)
add_subdirectory(sources/shiboken2)
# Semi-hack to include exported shiboken variables.
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/sources/shiboken2/data")
add_subdirectory(sources/pyside2)
# Semi-hack to include exported pyside2 variables.
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/sources/pyside2/libpyside")
add_subdirectory(sources/pyside2-tools)
LICENSE.COMMERCIAL 0000664 0000000 0000000 00000134304 13766170131 0013507 0 ustar 00root root 0000000 0000000 QT LICENSE AGREEMENT Agreement version 4.0
This License Agreement (“Agreement”) is a legal agreement between The Qt
Company (as defined below) and the Licensee (as defined below) for the license
of Licensed Software (as defined below). Capitalized terms used herein are
defined in Section 1.
WHEREAS:
(A). Licensee wishes to use the Licensed Software for the purpose of developing
and distributing Applications and/or Devices; and
(B). The Qt Company is willing to grant the Licensee a right to use Licensed
Software for such purpose pursuant to term and conditions of this Agreement.
NOW, THEREFORE, THE PARTIES HEREBY AGREE AS FOLLOWS:
1. DEFINITIONS
“Affiliate” of a Party shall mean an entity (i) which is directly or indirectly
controlling such Party; (ii) which is under the same direct or indirect
ownership or control as such Party; or (iii) which is directly or indirectly
owned or controlled by such Party. For these purposes, an entity shall be
treated as being controlled by another if that other entity has fifty percent
(50 %) or more of the votes in such entity, is able to direct its affairs
and/or to control the composition of its board of directors or equivalent body.
“Applications” shall mean Licensee's software products created using the
Licensed Software, which may include the Redistributables, or part
thereof.
“Contractor(s)” shall mean third party consultants, distributors and
contractors performing services to a Party under applicable contractual
arrangement.
“Customer(s)” shall mean Licensee’s end users to whom Licensee, directly or
indirectly, distributes copies of the Redistributables.
“Deployment Platforms” shall mean operating systems specified in the License
Certificate, in which the Redistributables can be distributed pursuant to the
terms and conditions of this Agreement.
“Designated User(s)” shall mean the employee(s) of Licensee or Licensee’s
Affiliates acting within the scope of their employment or Licensee's
Contractors acting within the scope of their services for Licensee and on
behalf of Licensee. Designated Users shall be named in the License Certificate.
“Development License” shall mean the license needed by the Licensee for each
Designated User to use the Licensed Software under the license grant described
in Section 3.1 of this Agreement.
“Development Platforms” shall mean those operating systems specified in the
License Certificate, in which the Licensed Software can be used under the
Development License, but not distributed in any form or used for any other
purpose.
“Devices” shall mean hardware devices or products that 1) are manufactured
and/or distributed by the Licensee or its Affiliates or Contractors, and
(2)(i) incorporate or integrate the Redistributables or parts thereof; or (ii)
do not incorporate or integrate the Redistributables at the time of
distribution, but where, when used by a Customer, the main user interface or
substantial functionality of such device is provided by Application(s) or
otherwise depends on the Licensed Software.
“Distribution License(s)” shall mean the license required for distribution of
Redistributables in connection with Devices pursuant to license grant described
in Section 3.3 of this Agreement.
“Distribution License Packs” shall mean set of prepaid Distribution Licenses
for distribution of Redistributables, as defined in The Qt Company’s standard
price list, quote, Purchase Order confirmation or in an appendix hereto,
as the case may be.
“Intellectual Property Rights” shall mean patents (including utility models),
design patents, and designs (whether or not capable of registration), chip
topography rights and other like protection, copyrights, trademarks, service
marks, trade names, logos or other words or symbols and any other form of
statutory protection of any kind and applications for any of the foregoing as
well as any trade secrets.
“License Certificate” shall mean a certificate generated by The Qt Company for
each Designated User respectively upon them downloading the licensed Software.
License Certificate will be available under respective Designated User’s Qt
Account at account.qt.io and it will specify the Designated User, the
Development Platforms, Deployment Platforms and the License Term. The terms of
the License Certificate are considered part of this Agreement and shall be
updated from time to time to reflect any agreed changes to the foregoing terms
relating to Designated User’s rights to the Licensed Software.
“License Fee” shall mean the fee charged to the Licensee for rights granted
under the terms of this Agreement.
“License Term” shall mean the agreed validity period of the Development
License of the respective Designated User, during which time the
Designated User is entitled to use the Licensed Software, as set forth in the
respective License Certificate.
“Licensed Software” shall mean all versions of the
(i) Qt Toolkit (including Qt Essentials, Qt Add-Ons and Value-Add modules) as
described in http://doc.qt.io/qt-5/qtmodules.html,
(ii). Qt Creator (including Creator IDE tool) as described in
http://doc.qt.io/qtcreator/index.html,
(iii). Qt 3D Studio as described in http://doc.qt.io/qt3dstudio/index.html, and
as well as corresponding online or electronic documentation, associated media
and printed materials, including the source code, example programs and the
documentation, licensed to the Licensee under this Agreement. Licensed Software
does not include Third Party Software (as defined in Section 4), Open Source
Qt, or other software products of The Qt Company (for example Qt Safe Renderer
and Qt for Automation), unless such other software products of The Qt Company
are separately agreed in writing to be included in scope of the Licensed
Software.
“Licensee” shall mean the individual or legal entity that is party to this
Agreement, as identified on the signature page hereof.
“Licensee’s Records” shall mean books and records that are likely to contain
information bearing on Licensee’s compliance with this Agreement or the
payments due to The Qt Company under this Agreement, including, but not limited
to: assembly logs, sales records and distribution records.
“Modified Software” shall have the meaning as set forth in Section 2.3.
“Online Services” shall mean any services or access to systems made available
by The Qt Company to the Licensee over the Internet relating to the Licensed
Software or for the purpose of use by the Licensee of the Licensed Software or
Support. Use of any such Online Services is discretionary for the Licensee and
some of them may be subject to additional fees.
“Open Source Qt” shall mean the non-commercial Qt computer software products,
licensed under the terms of the GNU Lesser General Public License, version
2.1 or later (“LGPL”) or the GNU General Public License, version 2.0 or later
(“GPL”). For clarity, Open Source Qt shall not be provided nor governed under
this Agreement.
”Party” or “Parties” shall mean Licensee and/or The Qt Company.
"Redistributables" shall mean the portions of the Licensed Software set forth
in Appendix 1, Section 1 that may be distributed pursuant to the terms of this
Agreement in object code form only, including any relevant documentation.
Where relevant, any reference to Licensed Software in this Agreement shall
include and refer also to Redistributables.
“Renewal Term” shall mean an extension of previous License Term as agreed
between the Parties.
“Submitted Modified Software” shall have the meaning as set forth in
Section 2.3.
“Support” shall mean standard developer support that is provided by The Qt
Company to assist Designated Users in using the Licensed Software in
accordance with The Qt Company’s standard support terms and as further
defined in Section 8 hereunder.
“Taxes” shall have the meaning set forth in Section 10.5.
“Term” shall have the meaning set forth in Section 12.
“The Qt Company” shall mean:
(i) in the event Licensee is an individual residing in the United States or a
legal entity incorporated in the United States or having its headquarters in
the United States, The Qt Company Inc., a Delaware corporation with its office
at 2350 Mission College Blvd., Suite 1020, Santa Clara, CA 95054, USA.; or
(ii) in the event the Licensee is an individual residing outside of the United
States or a legal entity incorporated outside of the United States or having
its registered office outside of the United States, The Qt Company Ltd., a
Finnish company with its registered office at Bertel Jungin aukio D3A, 02600
Espoo, Finland.
"Third Party Software " shall have the meaning set forth in Section 4.
“Updates” shall mean a release or version of the Licensed Software containing
bug fixes, error corrections and other changes that are generally made
available to users of the Licensed Software that have contracted for Support.
Updates are generally depicted as a change to the digits following the decimal
in the Licensed Software version number. The Qt Company shall make Updates
available to the Licensee under the Support. Updates shall be considered as
part of the Licensed Software hereunder.
“Upgrades” shall mean a release or version of the Licensed Software containing
enhancements and new features and are generally depicted as a change to the
first digit of the Licensed Software version number. In the event Upgrades are
provided to the Licensee under this Agreement, they shall be considered as
part of the Licensed Software hereunder.
2. OWNERSHIP
2.1 Ownership of The Qt Company
The Licensed Software is protected by copyright laws and international
copyright treaties, as well as other intellectual property laws and treaties.
The Licensed Software is licensed, not sold.
All The Qt Company's Intellectual Property Rights are and shall remain the
exclusive property of The Qt Company or its licensors respectively.
2.2 Ownership of Licensee
All the Licensee's Intellectual Property Rights are and shall remain the
exclusive property of the Licensee or its licensors respectively.
All Intellectual Property Rights to the Modified Software, Applications and
Devices shall remain with the Licensee and no rights thereto shall be granted
by the Licensee to The Qt Company under this Agreement (except as set forth in
Section 2.3 below).
2.3 Modified Software
Licensee may create bug-fixes, error corrections, patches or modifications to
the Licensed Software (“Modified Software”). Such Modified Software may break
the source or binary compatibility with the Licensed Software (including
without limitation through changing the application programming interfaces
("API") or by adding, changing or deleting any variable, method, or class
signature in the Licensed Software and/or any inter-process protocols, services
or standards in the Licensed Software libraries). To the extent that Licensee’s
Modified Software so breaks source or binary compatibility with the Licensed
Software, Licensee acknowledges that The Qt Company's ability to provide
Support may be prevented or limited and Licensee's ability to make use of
Updates may be restricted.
Licensee may, at its sole and absolute discretion, choose to submit Modified
Software to The Qt Company (“Submitted Modified Software”) in connection with
Licensee’s Support request, service request or otherwise. In the event Licensee
does so, then, Licensee hereby grants The Qt Company a sublicensable,
assignable, irrevocable, perpetual, worldwide, non-exclusive, royalty-free and
fully paid-up license, under all of Licensee’s Intellectual Property Rights, to
reproduce, adapt, translate, modify, and prepare derivative works of, publicly
display, publicly perform, sublicense, make available and distribute such
Submitted Modified Software as The Qt Company sees fit at its free and absolute
discretion.
3. LICENSES GRANTED
3.1 Development with Licensed Software
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
personal, worldwide, non-exclusive, non-transferable license, valid for the
License Term, to use, modify and copy the Licensed Software by Designated Users
on the Development Platforms for the sole purposes of designing, developing,
demonstrating and testing Application(s) and/or Devices, and to provide thereto
related support and other related services to end-user Customers.
Licensee may install copies of the Licensed Software on an unlimited number of
computers provided that (i) only the Designated Users may use the Licensed
Software, and (ii) all Designated Users must have a valid Development License
to use Licensed Software.
Licensee may at any time designate another Designated User to replace a then-
current Designated User by notifying The Qt Company in writing, provided that
any Designated User may be replaced only once during any six-month period.
Upon expiry of the initially agreed License Term, the respective License Terms
shall be automatically extended to one or more Renewal Term(s), unless and
until either Party notifies the other Party in writing that it does not wish to
continue the License Term, such notification to be provided to the other Party
no less than ninety (90) days before expiry of the respective License Term.
Unless otherwise agreed between the Parties, Renewal Term shall be of equal
length with the initial Term.
Any such Renewal Term shall be subject to License Fees agreed between the
Parties or, if no advance agreement exists, subject to The Qt Company’s
standard pricing applicable at the commencement date of any such Renewal Term.
3.2 Distribution of Applications
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
personal, worldwide, non-exclusive, non-transferable, revocable (for cause
pursuant to this Agreement) right and license, valid for the Term, to
(i) distribute, by itself or through its Contractors, Redistributables as
installed, incorporated or integrated into Applications for execution on the
Deployment Platforms, and
(ii) grant sublicenses to Redistributables, as distributed hereunder, for
Customers solely for Customer’s internal use and to the extent necessary in
order for the Customers to use the Applications for their respective intended
purposes.
Right to distribute the Redistributables as part of an Application as provided
herein is not royalty-bearing but is conditional upon the Licensee having paid
the agreed Development Licenses from The Qt Company before distributing any
Redistributables to Customers.
3.3 Distribution of Devices
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
personal, worldwide, non-exclusive, non-transferable, revocable (for cause
pursuant to this Agreement) right and license, valid for the Term, to
(i) distribute, by itself or through one or more tiers of Contractors,
Redistributables as installed, incorporated or integrated, or intended to be
installed, incorporated or integrated into Devices for execution on the
Deployment Platforms, and
(ii) grant sublicenses to Redistributables, as distributed hereunder, for
Customers solely for Customer’s internal use and to the extent necessary in
order for the Customers to use the Devices for their respective intended
purposes.
Right to distribute the Redistributables with Devices as provided herein is
conditional upon the Licensee having purchased and paid the appropriate amount
of Development and Distribution Licenses from The Qt Company before
distributing any Redistributables to Customers.
3.4 Further Requirements
The licenses granted above in this Section 3 by The Qt Company to Licensee are
conditional and subject to Licensee's compliance with the following terms:
(i) Licensee shall not remove or alter any copyright, trademark or other
proprietary rights notice contained in any portion of the Licensed Software;
(ii) Applications must add primary and substantial functionality to the
Licensed Software;
(iii) Applications may not pass on functionality which in any way makes it
possible for others to create software with the Licensed Software; provided
however that Licensee may use the Licensed Software's scripting and QML ("Qt
Quick") functionality solely in order to enable scripting, themes and styles
that augment the functionality and appearance of the Application(s) without
adding primary and substantial functionality to the Application(s);
(iv) Applications must not compete with the Licensed Software;
(v) Licensee shall not use The Qt Company's or any of its suppliers' names,
logos, or trademarks to market Applications, except that Licensee may use
“Built with Qt” logo to indicate that Application(s) was developed using the
Licensed Software;
(vi) Licensee shall not distribute, sublicense or disclose source code of
Licensed Software to any third party (provided however that Licensee may
appoint employee(s) of Contractors as Designated Users to use Licensed
Software pursuant to this Agreement). Such right may be available for the
Licensee subject to a separate software development kit (“SDK”) license
agreement to be concluded with The Qt Company;
(vii) Licensee shall not grant the Customers a right to (i) make copies of the
Redistributables except when and to the extent required to use the Applications
and/or Devices for their intended purpose, (ii) modify the Redistributables or
create derivative works thereof, (iii) decompile, disassemble or otherwise
reverse engineer Redistributables, or (iv) redistribute any copy or portion of
the Redistributables to any third party, except as part of the onward sale of
the Device on which the Redistributables are installed;
(viii) Licensee shall not and shall cause that its Affiliates or Contractors
shall not a) in any way combine, incorporate or integrate Licensed Software
with, or use Licensed Software for creation of, any software created with or
incorporating Open Source Qt, or b) incorporate or integrate Applications
into a hardware device or product other than a Device, unless Licensee has
received an advance written permission from The Qt Company to do so. Absent
such written permission, any and all distribution by the Licensee during the
Term of a hardware device or product a) which incorporate or integrate any
part of Licensed Software or Open Source Qt; or b) where the main user
interface or substantial functionality is provided by software build with
Licensed Software or Open Source Qt or otherwise depends on the Licensed
Software or Open Source Qt, shall be considered as a Device distribution under
this Agreement and dependent on compliance thereof (including but not limited
to obligation to pay applicable License Fees for such distribution);
(ix) Licensee shall cause all of its Affiliates and Contractors entitled to
make use of the licenses granted under this Agreement, to be contractually
bound to comply with the relevant terms of this Agreement and not to use the
Licensed Software beyond the terms hereof and for any purposes other than
operating within the scope of their services for Licensee. Licensee shall be
responsible for any and all actions and omissions of its Affiliates and
Contractors relating to the Licensed Software and use thereof (including but
not limited to payment of all applicable License Fees);
(x) Except when and to the extent explicitly provided in this Section 3,
Licensee shall not transfer, publish, disclose, display or otherwise make
available the Licensed Software;
; and
(xi) Licensee shall not attempt or enlist a third party to conduct or attempt
to conduct any of the above.
Above terms shall not be applicable if and to the extent they conflict with any
mandatory provisions of any applicable laws.
Any use of Licensed Software beyond the provisions of this Agreement is
strictly prohibited and requires an additional license from The Qt Company.
4. THIRD PARTY SOFTWARE
The Licensed Software may provide links to third party libraries or code
(collectively "Third Party Software") to implement various functions. Third
Party Software does not comprise part of the Licensed Software. In some cases,
access to Third Party Software may be included in the Licensed Software. Such
Third Party Software will be listed in the ".../src/3rdparty" source tree
delivered with the Licensed Software or documented in the Licensed Software, as
such may be amended from time to time. Licensee acknowledges that use or
distribution of Third Party Software is in all respects subject to applicable
license terms of applicable third party right holders.
5. PRE-RELEASE CODE
The Licensed Software may contain pre-release code and functionality marked or
otherwise stated as “Technology Preview”, “Alpha”, “Beta” or similar
designation. Such pre-release code may be present in order to provide
experimental support for new platforms or preliminary versions of one or more
new functionalities. The pre-release code may not be at the level of
performance and compatibility of a final, generally available, product
offering of the Licensed Software. The pre-release parts of the Licensed
Software may not operate correctly, may contain errors and may be substantially
modified by The Qt Company prior to the first commercial product release, if
any. The Qt Company is under no obligation to make pre-release code
commercially available, or provide any Support or Updates relating thereto. The
Qt Company assumes no liability whatsoever regarding any pre-release code, but
any use thereof is exclusively at Licensee’s own risk and expense.
6. LIMITED WARRANTY AND WARRANTY DISCLAIMER
The Qt Company hereby represents and warrants that it has the power and
authority to grant the rights and licenses granted to Licensee under this
Agreement.
Except as set forth above, the Licensed Software is licensed to Licensee
"as is" and Licensee’s exclusive remedy and The Qt Company’s entire liability
for errors in the Licensed Software shall be limited, at The Qt Company’s
option, to correction of the error, replacement of the Licensed Software or
return of the applicable fees paid for the defective Licensed Software for the
time period during which the License is not able to utilize the Licensed
Software under the terms of this Agreement.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE QT COMPANY ON BEHALF OF
ITSELF AND ITS LICENSORS, SUPPLIERS AND AFFILIATES, DISCLAIMS ALL OTHER
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-
INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE. THE QT COMPANY DOES NOT
WARRANT THAT THE LICENSED SOFTWARE WILL SATISFY LICENSEE’S REQUIREMENTS OR THAT
IT WILL OPERATE WITHOUT DEFECT OR ERROR OR THAT THE OPERATION THEREOF WILL BE
UNINTERRUPTED. ALL USE OF AND RELIANCE ON THE LICENSED SOFTWARE IS AT THE SOLE
RISK OF AND RESPONSIBILITY OF LICENSEE.
7. INDEMNIFICATION AND LIMITATION OF LIABILITY
7.1 Limitation of Liability
EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II)
BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO
EVENT SHALL EITHER PARTY BE LIABLE TO THE OTHER PARTY FOR ANY LOSS OF PROFIT,
LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, SPECIAL,
CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY KIND,
HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THIS AGREEMENT. PARTIES
SPECIFICALLY AGREE THAT LICENSEE’S OBLIGATION TO PAY LICENSE AND OTHER FEES
CORRESPONDING TO ACTUAL USAGE OF LICENSED SOFTWARE HEREUNDER SHALL BE
CONSIDERED AS A DIRECT DAMAGE.
EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II)
BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN
NO EVENT SHALL EITHER PARTY’S TOTAL AGGREGATE LIABILITY UNDER THIS AGREEMENT
EXCEED THE AGGREGATE LICENSE FEES PAID OR PAYABLE TO THE QT COMPANY FROM
LICENSEE DURING THE PERIOD OF TWELVE (12) MONTHS IMMEDIATELY PRECEDING THE
EVENT RESULTING IN SUCH LIABILITY.
THE PROVISIONS OF THIS SECTION 7 ALLOCATE THE RISKS UNDER THIS AGREEMENT
BETWEEN THE QT COMPANY AND LICENSEE AND THE PARTIES HAVE RELIED UPON THE
LIMITATIONS SET FORTH HEREIN IN DETERMINING WHETHER TO ENTER INTO THIS AGREEMENT.
7.2 Licensee´s Indemnification
Licensee shall indemnify and hold harmless The Qt Company from and against any
claim, injury, judgment, settlement, loss or expense, including attorneys' fees
related to: (a) Licensee’s misrepresentation in connection with The Qt Company
or the Licensed Software or breach of this Agreement, (b) the Application or
Device (except where such cause of liability is solely attributable to the
Licensed Software).
8. SUPPORT, UPDATES AND ONLINE SERVICES
Upon due payment of the agreed License Fees the Licensee will be eligible to
receive Support and Updates and to use the Online Services during the License
Term, provided, however, that in the event the License Term is longer than 36
months, Support is provided only for the first 12 months, unless the Parties
specifically otherwise agree.
Unless otherwise decided by The Company at its free and absolute discretion,
Upgrades will not be included in the Support but may be available subject to
additional fees.
From time to time The Qt Company may change the Support terms, provided that
during the respective ongoing License Term the level of Support provided by The
Qt Company may not be reduced without the consent of the Licensee.
Unless otherwise agreed, The Qt Company shall not be responsible for providing
any service or support to Customers.
9. CONFIDENTIALITY
Each Party acknowledges that during the Term of this Agreement each Party may
receive information about the other Party's business, business methods,
business plans, customers, business relations, technology, and other
information, including the terms of this Agreement, that is confidential and
of great value to the other Party, and the value of which would be
significantly reduced if disclosed to third parties (“Confidential
Information”). Accordingly, when a Party (the “Receiving Party”) receives
Confidential Information from the other Party (the “Disclosing Party”), the
Receiving Party shall only disclose such information to employees and
Contractors on a need to know basis, and shall cause its employees and
employees of its Affiliates to: (i) maintain any and all Confidential
Information in confidence; (ii) not disclose the Confidential Information to a
third party without the Disclosing Party's prior written approval; and (iii)
not, directly or indirectly, use the Confidential Information for any purpose
other than for exercising its rights and fulfilling its responsibilities
pursuant to this Agreement. Each Party shall take reasonable measures to
protect the Confidential Information of the other Party, which measures shall
not be less than the measures taken by such Party to protect its own
confidential and proprietary information.
Obligation of confidentiality shall not apply to information that (i) is or
becomes generally known to the public through no act or omission of the
Receiving Party; (ii) was in the Receiving Party's lawful possession prior to
the disclosure hereunder and was not subject to limitations on disclosure or
use; (iii) is developed independently by employees or Contractors of the
Receiving Party or other persons working for the Receiving Party who have not
had access to the Confidential Information of the Disclosing Party, as proven
by the written records of the Receiving Party; (iv) is lawfully disclosed to
the Receiving Party without restrictions, by a third party not under an
obligation of confidentiality; or (v) the Receiving Party is legally compelled
to disclose, in which case the Receiving Party shall notify the Disclosing
Party of such compelled disclosure and assert the privileged and confidential
nature of the information and cooperate fully with the Disclosing Party to
limit the scope of disclosure and the dissemination of disclosed Confidential
Information to the minimum extent necessary.
The obligations under this Section 9 shall continue to remain in force for a
period of five (5) years after the last disclosure, and, with respect to trade
secrets, for so long as such trade secrets are protected under applicable trade
secret laws.
10. FEES, DELIVERY AND PAYMENT
10.1 License Fees
License Fees are described in The Qt Company’s standard price list, quote or
Purchase Order confirmation or in an appendix hereto, as the case may be.
The License Fees shall not be refunded or claimed as a credit in any event or
for any reason whatsoever.
10.2 Ordering Licenses
Licensee may purchase Development Licenses and Distribution Licenses pursuant
to agreed pricing terms or, if no specific pricing terms have been agreed upon,
at The Qt Company's standard pricing terms applicable at the time of purchase.
Licensee shall submit all purchase orders for Development Licenses and
Distribution Licenses to The Qt Company by email or any other method acceptable
to The Qt Company (each such order is referred to herein as a “Purchase Order”)
for confirmation, whereupon the Purchase Order shall become binding between the
Parties.
10.3 Distribution License Packs
Unless otherwise agreed, Distribution Licenses shall be purchased by way of
Distribution License Packs.
Upon due payment of the ordered Distribution License Pack(s), the Licensee will
have an account of Distribution Licenses available for installing, bundling or
integrating (all jointly “installing”) the Redistributables with the Devices or
for otherwise distributing the Redistributables in accordance with this
Agreement.
Each time Licensee “installs” or distributes a copy of Redistributables, then
one Distribution License is used, and Licensee’s account of available
Distribution Licenses is decreased accordingly.
Licensee may “install” copies of the Redistributables so long as Licensee has
Distribution Licenses remaining on its account.
Redistributables will be deemed to have been “installed” into a Device when one
of the following circumstances shall have occurred: a) the Redistributables
have been loaded onto the Device and used outside of the Licensee’s premises or
b) the Device has been fully tested and placed into Licensee's inventory
(or sold) for the first time (i.e., Licensee will not be required to use
(or pay for) more than one Distribution License for each individual Device,
e.g. in a situation where a Device is returned to Licensee's inventory after
delivery to a distributor or sale to a Customer). In addition, if Licensee
includes a back-up copy of the Redistributables on a CD-ROM or other storage
medium along with the product, that backup copy of the Redistributables will
not be deemed to have been “installed” and will not require an additional
Distribution License.
10.4 Payment Terms
License Fees and any other charges under this Agreement shall be paid by
Licensee no later than thirty (30) days from the date of the applicable invoice
from The Qt Company.
The Qt Company will submit an invoice to Licensee after the date of this
Agreement and/or after The Qt Company receives a Purchase Order from
Licensee.
A late payment charge of the lower of (a) one percent per month; or (b) the
interest rate stipulated by applicable law, shall be charged on any unpaid
balances that remain past due.
The Qt Company shall have the right to suspend, terminate or withhold grants
of all rights to the Licensed Software hereunder, including but not limited to
the Developer License, Distribution License, and Support, should Licensee fail
to make payment in timely fashion.
10.5 Taxes
All License Fees and other charges payable hereunder are gross amounts but
exclusive of any value added tax, use tax, sales tax and other taxes, duties or
tariffs (“Taxes”). Such applicable Taxes shall be paid by Licensee, or, where
applicable, in lieu of payment of such Taxes, Licensee shall provide an
exemption certificate to The Qt Company and any applicable authority.
11 RECORD-KEEPING AND REPORTING OBLIGATIONS; AUDIT RIGHTS
11.1 Licensee’s Record-keeping
Licensee shall at all times maintain accurate and up-to-date written records of
Licensee’s activities related to the use of Licensed Software and distribution
of Redistributables. The records shall be adequate to determine Licensee’s
compliance with the provisions of this Agreement and to demonstrate the number
of Designated Users and Redistributables distributed by Licensee. The records
shall conform to good accounting practices reasonably acceptable to The Qt
Company.
Licensee shall, within thirty (30) days from receiving The Qt Company’s request
to that effect, deliver to The Qt Company a report on Licensee’s usage of
Licensed Software, such report to copies of Redistributables distributed by
Licensee during that calendar quarter, and also detailing the number of
undistributed copies of Redistributables made by Licensee and remaining in its
account contain information, in sufficient detail, on (i) amount of users
working with Licensed Software, (ii) copies of Redistributables distributed by
Licensee during that calendar quarter, (iii) number of undistributed copies of
Redistributables and corresponding number of unused Distribution Licenses
remaining on Licensee’s account, and (iv) any other information as The Qt
Company may reasonably require from time to time.
11.2. The Qt Company’s Audit Rights
The Qt Company or an independent auditor acting on behalf of The Qt Company’s,
may, upon at least five (5) business days’ prior written notice and at its
expense, audit Licensee with respect to the use of the Redistributables, but
not more frequently than once during each 6-month period. Such audit may be
conducted by mail, electronic means or through an in-person visit to Licensee’s
place of business. Any such in-person audit shall be conducted during regular
business hours at Licensee's facilities and shall not unreasonably interfere
with Licensee's business activities. The Qt Company or the independent auditor
acting on behalf of The Qt Company shall be entitled to inspect Licensee’s
Records. All such Licensee’s Records and use thereof shall be subject to an
obligation of confidentiality under this Agreement.
If an audit reveals that Licensee is using the Licensed Software beyond scope
of the licenses Licensee has paid for, Licensee agrees to immediately pay The
Qt Company any amounts owed for such unauthorized use.
In addition, in the event the audit reveals a material violation of the terms
of this Agreement (underpayment of more than 5% of License Fees shall always be
deemed a material violation for purposes of this section), then the Licensee
shall pay The Qt Company's reasonable cost of conducting such audit.
12 TERM AND TERMINATION
12.1 Term
This Agreement shall enter into force upon due acceptance by both Parties and
remain in force for as long as there is any Development License(s) in force
(“Term”), unless and until terminated pursuant to the terms of this Section 12.
12.2 Termination by The Qt Company
The Qt Company shall have the right to terminate this Agreement upon thirty
(30) days prior written notice if the Licensee is in material breach of any
obligation of this Agreement and fails to remedy such breach within such notice
period.
12.3 Mutual Right to Terminate
Either Party shall have the right to terminate this Agreement immediately upon
written notice in the event that the other Party becomes insolvent, files for
any form of bankruptcy, makes any assignment for the benefit of creditors, has
a receiver, administrative receiver or officer appointed over the whole or a
substantial part of its assets, ceases to conduct business, or an act
equivalent to any of the above occurs under the laws of the jurisdiction of the
other Party.
12.4 Parties´ Rights and Duties upon Termination
Upon expiry or termination of the Agreement Licensee shall cease and shall
cause all Designated Users (including those of its Affiliates’ and
Contractors’) to cease using the Licensed Software and distribution of the
Redistributables under this Agreement.
Notwithstanding the above, in the event the Agreement expires or is terminated:
(i) as a result of The Qt Company choosing not to renew the Development
License(s) as set forth in Section 3.1, then all valid licenses possessed by
the Licensee at such date shall be extended to be valid in perpetuity under the
terms of this Agreement and Licensee is entitled to purchase additional
licenses as set forth in Section 10.2; or
(ii) for reason other than by The Qt Company pursuant to item (i) above or
pursuant to Section 12.2, then the Licensee is entitled, for a period of six
(6) months after the effective date of termination, to continue distribution of
Devices under the Distribution Licenses paid but unused at such effective date
of termination.
Upon any such termination the Licensee shall destroy or return to The Qt
Company all copies of the Licensed Software and all related materials and will
certify the same to The Qt Company upon its request, provided however that
Licensee may retain and exploit such copies of the Licensed Software as it may
reasonably require in providing continued support to Customers.
Expiry or termination of this Agreement for any reason whatsoever shall not
relieve Licensee of its obligation to pay any License Fees accrued or payable
to The Qt Company prior to the effective date of termination, and Licensee
shall immediately pay to The Qt Company all such fees upon the effective date
of termination. Termination of this Agreement shall not affect any rights of
Customers to continue use of Applications and Devices (and therein incorporated
Redistributables).
12.5 Extension in case of bankruptcy
In the event The Qt Company is declared bankrupt under a final, non-cancellable
decision by relevant court of law, and this Agreement is not, at the date of
expiry of the Development License(s) pursuant to Section 3.1, assigned to
party, who has assumed The Qt Company’s position as a legitimate licensor of
Licensed Software under this Agreement, then all valid licenses possessed by
the Licensee at such date of expiry, and which the Licensee has not notified
for expiry, shall be extended to be valid in perpetuity under the terms of
this Agreement.
13. GOVERNING LAW AND LEGAL VENUE
In the event this Agreement is in the name of The Qt Company Inc., a Delaware
Corporation, then:
(i) this Agreement shall be construed and interpreted in accordance with the
laws of the State of California, USA, excluding its choice of law provisions;
(ii) the United Nations Convention on Contracts for the International Sale of
Goods will not apply to this Agreement; and
(iii) any dispute, claim or controversy arising out of or relating to this
Agreement or the breach, termination, enforcement, interpretation or validity
thereof, including the determination of the scope or applicability of this
Agreement to arbitrate, shall be determined by arbitration in San Francisco,
USA, before one arbitrator. The arbitration shall be administered by JAMS
pursuant to JAMS' Streamlined Arbitration Rules and Procedures. Judgment on the
Award may be entered in any court having jurisdiction. This Section shall not
preclude parties from seeking provisional remedies in aid of arbitration from a
court of appropriate jurisdiction.
In the event this Agreement is in the name of The Qt Company Ltd., a Finnish
Company, then:
(i) this Agreement shall be construed and interpreted in accordance with the
laws of Finland, excluding its choice of law provisions;
(ii) the United Nations Convention on Contracts for the International Sale of
Goods will not apply to this Agreement; and
(iii) any disputes, controversy or claim arising out of or relating to this
Agreement, or the breach, termination or validity thereof shall be shall be
finally settled by arbitration in accordance with the Arbitration Rules of
Finland Chamber of Commerce. The arbitration tribunal shall consist of one (1),
or if either Party so requires, of three (3), arbitrators. The award shall be
final and binding and enforceable in any court of competent jurisdiction. The
arbitration shall be held in Helsinki, Finland and the process shall be
conducted in the English language. This Section shall not preclude parties from
seeking provisional remedies in aid of arbitration from a court of appropriate
jurisdiction.
14. GENERAL PROVISIONS
14.1 No Assignment
Except in the case of a merger or sale of substantially all of its corporate
assets, Licensee shall not be entitled to assign or transfer all or any of its
rights, benefits and obligations under this Agreement without the prior written
consent of The Qt Company, which shall not be unreasonably withheld or delayed.
The Qt Company shall be entitled to freely assign or transfer any of its
rights, benefits or obligations under this Agreement.
14.2 No Third Party Representations
Licensee shall make no representations or warranties concerning the Licensed
Software on behalf of The Qt Company. Any representation or warranty Licensee
makes or purports to make on The Qt Company’s behalf shall be void as to The
Qt Company.
14.3 Surviving Sections
Any terms and conditions that by their nature or otherwise reasonably should
survive termination of this Agreement shall so be deemed to survive.
14.4 Entire Agreement
This Agreement, the exhibits hereto, the License Certificate and any applicable
Purchase Order constitute the complete agreement between the Parties and
supersedes all prior or contemporaneous discussions, representations, and
proposals, written or oral, with respect to the subject matters discussed
herein.
In the event of any conflict or inconsistency between this Agreement and any
Purchase Order, the terms of this Agreement will prevail over the terms of the
Purchase Order with respect to such conflict or inconsistency.
Parties specifically acknowledge and agree that this Agreement prevails over
any click-to-accept or similar agreements the Designated Users may need to
accept online upon download of the Licensed Software, as may be required by
The Qt Company’s applicable processes relating to Licensed Software.
14.5 Modifications
No modification of this Agreement shall be effective unless contained in a
writing executed by an authorized representative of each Party. No term or
condition contained in Licensee's Purchase Order shall apply unless expressly
accepted by The Qt Company in writing.
14.6 Force Majeure
Except for the payment obligations hereunder, neither Party shall be liable to
the other for any delay or non-performance of its obligations hereunder in the
event and to the extent that such delay or non-performance is due to an event
of act of God, terrorist attack or other similar unforeseeable catastrophic
event that prevents either Party for fulfilling its obligations under this
Agreement and which such Party cannot avoid or circumvent (“Force Majeure
Event”). If the Force Majeure Event results in a delay or non-performance of a
Party for a period of three (3) months or longer, then either Party shall have
the right to terminate this Agreement with immediate effect without any
liability (except for the obligations of payment arising prior to the event of
Force Majeure) towards the other Party.
14.7 Notices
Any notice given by one Party to the other shall be deemed properly given and
deemed received if specifically acknowledged by the receiving Party in writing
or when successfully delivered to the recipient by hand, fax, or special
courier during normal business hours on a business day to the addresses
specified for each Party on the signature page. Each communication and document
made or delivered by one Party to the other Party pursuant to this Agreement
shall be in the English language.
14.8 Export Control
Licensee acknowledges that the Redistributables may be subject to export
control restrictions under the applicable laws of respective countries.
Licensee shall fully comply with all applicable export license restrictions
and requirements as well as with all laws and regulations relating to the
Redistributables and exercise of licenses hereunder and shall procure all
necessary governmental authorizations, including without limitation, all
necessary licenses, approvals, permissions or consents, where necessary for the
re-exportation of the Redistributables, Applications and/or Devices.
14.9 No Implied License
There are no implied licenses or other implied rights granted under this
Agreement, and all rights, save for those expressly granted hereunder, shall
remain with The Qt Company and its licensors. In addition, no licenses or
immunities are granted to the combination of the Licensed Software with any
other software or hardware not delivered by The Qt Company under this Agreement.
14.10 Attorney Fees
The prevailing Party in any action to enforce this Agreement shall be entitled
to recover its attorney’s fees and costs in connection with such action.
14.11 Severability
If any provision of this Agreement shall be adjudged by any court of competent
jurisdiction to be unenforceable or invalid, that provision shall be limited or
eliminated to the minimum extent necessary so that this Agreement shall
otherwise remain in full force and effect and enforceable.
IN WITNESS WHEREOF, the Parties hereto, intending to be legally bound hereby,
have caused this Agreement to be executed by Licensee's authorized
representative installing the Licensed Software and accepting the terms
hereof in connection therewith.
Appendix 1
1. Parts of the Licensed Software that are permitted for distribution in
object code form only (“Redistributables”) under this Agreement:
- The Licensed Software's Qt Essentials and Qt Add-on libraries
- The Licensed Software's configuration tool (“qtconfig”)
- The Licensed Software's help tool (“Qt Assistant”)
- The Licensed Software's internationalization tools (“Qt Linguist”, “lupdate”,
“lrelease”)
- The Licensed Software's QML (“Qt Quick”) launcher tool (“qmlscene” or
“qmlviewer”)
- The Licensed Software's installer framework
- Qt for Python (PySide2)
2. Parts of the Licensed Software that are not permitted for distribution
include, but are not limited to:
- The Licensed Software's source code and header files
- The Licensed Software's documentation
- The Licensed Software’s documentation generation tool (“qdoc”)
- The Licensed Software's tool for writing makefiles (“qmake”)
- The Licensed Software's Meta Object Compiler (“moc”)
- The Licensed Software's User Interface Compiler (“uic”)
- The Licensed Software's Resource Compiler (“rcc”)
- The Licensed Software's parts of the IDE tool (“Qt Creator”)
- The Licensed Software’s parts of the Design tools (“Qt 3D Studio” or “Qt
Quick Designer”)
- The Licensed Software's Emulator
LICENSE.FDL 0000664 0000000 0000000 00000054661 13766170131 0012510 0 ustar 00root root 0000000 0000000 GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The "Document", below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall
subject (or to related matters) and contains nothing that could fall
directly within that overall subject. (Thus, if the Document is in
part a textbook of mathematics, a Secondary Section may not explain
any mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
The "publisher" means any person or entity that distributes copies of
the Document to the public.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no
other conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to
give them a chance to provide you with an updated version of the
Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct
from that of the Document, and from those of previous versions
(which should, if there were any, be listed in the History section
of the Document). You may use the same title as a previous version
if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five),
unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
giving the public permission to use the Modified Version under the
terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
public access to a Transparent copy of the Document, and likewise
the network locations given in the Document for previous versions
it was based on. These may be placed in the "History" section.
You may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
Preserve the Title of the section, and preserve in the section all
the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications". You must delete all sections
Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other
documents released under this License, and replace the individual
copies of this License in the various documents with a single copy
that is included in the collection, provided that you follow the rules
of this License for verbatim copying of each of the documents in all
other respects.
You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void, and
will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, receipt of a copy of some or all of the same material does
not give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of the
GNU Free Documentation License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this
License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the
Document.
11. RELICENSING
"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
World Wide Web server that publishes copyrightable works and also
provides prominent facilities for anybody to edit those works. A
public wiki that anybody can edit is an example of such a server. A
"Massive Multiauthor Collaboration" (or "MMC") contained in the site
means any set of copyrightable works thus published on the MMC site.
"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
license published by Creative Commons Corporation, a not-for-profit
corporation with a principal place of business in San Francisco,
California, as well as future copyleft versions of that license
published by that same organization.
"Incorporate" means to publish or republish a Document, in whole or in
part, as part of another Document.
An MMC is "eligible for relicensing" if it is licensed under this
License, and if all works that were first published under this License
somewhere other than this MMC, and subsequently incorporated in whole or
in part into the MMC, (1) had no cover texts or invariant sections, and
(2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site
under CC-BY-SA on the same site at any time before August 1, 2009,
provided the MMC is eligible for relicensing.
ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.
LICENSE.GPL2 0000664 0000000 0000000 00000043254 13766170131 0012603 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
LICENSE.GPLv3 0000664 0000000 0000000 00000105471 13766170131 0012772 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 3. That license references
the General Public License version 3, that is displayed below. Other
portions of the Qt Toolkit may be licensed directly under this license.
-------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
LICENSE.GPLv3-EXCEPT 0000664 0000000 0000000 00000107013 13766170131 0013752 0 ustar 00root root 0000000 0000000 This is the GNU General Public License version 3, annotated with The
Qt Company GPL Exception 1.0:
-------------------------------------------------------------------------
The Qt Company GPL Exception 1.0
Exception 1:
As a special exception you may create a larger work which contains the
output of this application and distribute that work under terms of your
choice, so long as the work is not otherwise derived from or based on
this application and so long as the work does not in itself generate
output that contains the output from this application in its original
or modified form.
Exception 2:
As a special exception, you have permission to combine this application
with Plugins licensed under the terms of your choice, to produce an
executable, and to copy and distribute the resulting executable under
the terms of your choice. However, the executable must be accompanied
by a prominent notice offering all users of the executable the entire
source code to this application, excluding the source code of the
independent modules, but including any changes you have made to this
application, under the terms of this license.
-------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
LICENSE.LGPLv3 0000664 0000000 0000000 00000017714 13766170131 0013110 0 ustar 00root root 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 3, which is displayed below.
This license makes reference to the version 3 of the GNU General
Public License, which you can find in the LICENSE.GPLv3 file.
-------------------------------------------------------------------------
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
README.cmake.md 0000664 0000000 0000000 00000003315 13766170131 0013423 0 ustar 00root root 0000000 0000000 # CMake super project
For development convenience, a CMake super project is included in the root of the repository.
The super project can be built using standalone CMake, or using an IDE's CMake integration
(Qt Creator for example).
Nevertheless the default build process is done via setup.py, in which case each of the
sub-projects are built and installed separately, as mentioned, the super project is just
for development convenience.
## IDE (Qt Creator) case
When using an IDE, just open the root CMakeLists.txt file as a new project, and make sure to
specify the following things:
* LLVM_INSTALL_DIR - the environment variable should point to your libclang library location
* Qt - either select a Qt Kit when configuring the project, or make sure that the
qmake binary is present in the PATH environment variable.
* Python - the PATH environment variable should also point to the Python interpreter
which you wish to use for building the projects (can either be a system
interpreter, or a virtualenv one for example)
Once that is done, just re-run CMake, so that it picks up the new environment values.
If needed, all other cache variables defined by the project files can be re-adjusted
(for example FORCE_LIMITED_API).
## Command line CMake case
When building using the command line CMake binary, make sure to invoke it in a separate
build directory, and not in the root source directory.
Make sure you have the correct environment variables set up, as described in the previous section.
The invocation would then look like:
```bash
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
# make or nmake or msbuild or jom
```
README.md 0000664 0000000 0000000 00000000532 13766170131 0012342 0 ustar 00root root 0000000 0000000 # Qt For Python
Qt For Python is the [Python Qt bindings project](http://wiki.qt.io/PySide2), providing
access to the complete Qt 5.x framework as well as to generator tools for rapidly
generating bindings for any C++ libraries.
shiboken2 is the generator used to build the bindings.
See README.pyside2.md and README.shiboken2.md for details.
README.pyside2.md 0000664 0000000 0000000 00000005552 13766170131 0013727 0 ustar 00root root 0000000 0000000 # PySide2
### Introduction
PySide2 is the official Python module from the
[Qt for Python project](http://wiki.qt.io/Qt_for_Python),
which provides access to the complete Qt 5.12+ framework.
The Qt for Python project is developed in the open, with all facilities you'd expect
from any modern OSS project such as all code in a git repository and an open
design process. We welcome any contribution conforming to the
[Qt Contribution Agreement](https://www.qt.io/contributionagreement/).
### Installation
Since the release of the [Technical Preview](https://blog.qt.io/blog/2018/06/13/qt-python-5-11-released/)
it is possible to install via `pip`, both from Qt's servers
and [PyPi](https://pypi.org/project/PySide2/):
pip install PySide2
#### Dependencies
PySide2 versions following 5.12 use a C++ parser based on
[Clang](http://clang.org/). The Clang library (C-bindings), version 6.0 or
higher is required for building. Prebuilt versions of it can be downloaded from
[download.qt.io](http://download.qt.io/development_releases/prebuilt/libclang/).
After unpacking the archive, set the environment variable *LLVM_INSTALL_DIR* to
point to the folder containing the *include* and *lib* directories of Clang:
7z x .../libclang-release_60-linux-Rhel7.2-gcc5.3-x86_64-clazy.7z
export LLVM_INSTALL_DIR=$PWD/libclang
On Windows:
7z x .../libclang-release_60-windows-vs2015_64-clazy.7z
SET LLVM_INSTALL_DIR=%CD%\libclang
### Building from source
For building PySide2 from scratch, please read about
[getting started](https://wiki.qt.io/Qt_for_Python/GettingStarted).
This process will include getting the code:
git clone https://code.qt.io/pyside/pyside-setup
cd pyside-setup
git branch --track 5.12 origin/5.12
git checkout 5.12
then install the dependencies, and following the instructions per platform.
A common build command will look like:
python setup.py install --qmake= --parallel=8 --build-tests
You can obtain more information about the options to build PySide
and Shiboken in [our wiki](https://wiki.qt.io/Qt_for_Python/).
### Documentation and Bugs
You can find more information about the PySide2 module API in the
[official Qt for Python documentation](https://doc.qt.io/qtforpython/).
If you come across any issue, please file a bug report at our
[JIRA tracker](https://bugreports.qt.io/projects/PYSIDE) following
our [guidelines](https://wiki.qt.io/Qt_for_Python/Reporting_Bugs).
### Community
Check *#qt-pyside*, our official IRC channel on FreeNode,
or contact us via our [mailing list](http://lists.qt-project.org/mailman/listinfo/pyside).
### Licensing
PySide2 is available under both Open Source (LGPLv3/GPLv2) and commercial license.
Using PyPi is the recommended installation source, because the content of the wheels is valid for both cases.
For more information, refer to the [Qt Licensing page](https://www.qt.io/licensing/).
README.shiboken2-generator.md 0000664 0000000 0000000 00000002643 13766170131 0016216 0 ustar 00root root 0000000 0000000 # Shiboken2-generator
Shiboken is the generator used by the Qt for Python project.
It outputs C++ code for CPython extensions, which can be compiled
and transformed into a Python module.
C++ projects based on Qt can be wrapped, but also projects
which are not related to Qt.
## How does it work?
Shiboken uses an API Extractor that does most of the job,
but it requires a typesystem (XML file) to customize how the
C++ classes/methods will be exposed to Python.
The typesystem allows you to remove arguments from signatures,
modify return types, inject code and add conversion rules
from the C++ data types to Python data types, manipulate
the ownership of the objects, etc.
# Examples
An example related to wrap a C++ library not depending on Qt
can be found in our [repository](https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples/samplebinding).
Additionally, you can find a couple of tests inside the
[git repository](https://code.qt.io/cgit/pyside/pyside-setup.git/tree/sources/shiboken2/tests).
For a more advanced case regarding extending a Qt/C++ application
with Python bindings based on the idea of the PySide module,
you can check the [scriptableapplication](https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples/scriptableapplication)
example in our repository.
# Documentation
You can find more information about Shiboken in our
[official documentation page](https://doc.qt.io/qtforpython/shiboken2/).
README.shiboken2.md 0000664 0000000 0000000 00000001156 13766170131 0014230 0 ustar 00root root 0000000 0000000 # Shiboken2 module
The purpose of the [shiboken2 Python module](https://wiki.qt.io/Qt_for_Python/Shiboken)
is to access information related to the binding generation that could be used to integrate
C++ programs to Python, or even to get useful information to debug
an application.
Mostly the idea is to interact with Shiboken objects,
where one can check if it is valid, or if the generated Python wrapper
is invalid after the underlying C++ object has been destroyed.
More information on the available functions can be found
in our [official documentation](https://doc.qt.io/qtforpython/shiboken2/shibokenmodule.html)
build_history/ 0000775 0000000 0000000 00000000000 13766170131 0013743 5 ustar 00root root 0000000 0000000 build_history/blacklist.txt 0000664 0000000 0000000 00000003521 13766170131 0016455 0 ustar 00root root 0000000 0000000 [pysidetest::delegatecreateseditor_test]
qt5.6
[pysidetest::modelview_test]
darwin py3
[pysidetest::qvariant_test]
darwin py3
[pysidetest::utils_test]
win32
[signals::signal_signature_test]
linux
darwin
win32
[Qt3DExtras::qt3dextras_test]
linux
darwin
[QtCore::qfile_test]
win32
darwin py3
[QtCore::qfileread_test]
darwin
# Nested exception in Python 3
[QtCore::qflags_test]
py3
[QtCore::qobject_connect_notify_test]
linux
darwin
win32
[QtGui::qmatrix_test]
win32
[QtWidgets::bug_576]
linux
win32
darwin py3
[QtWidgets::returnquadruplesofnumbers_test]
linux
darwin
win32
[QtWidgets::qstandarditemmodel_test]
py2
py3
[QtTest::touchevent_test]
linux
darwin
win32
[QtMultimedia::audio_test]
linux
darwin
win32
[QtQml::bug_951]
py3
[QtQml::javascript_exceptions]
py3
[QtScript::qscriptvalue_test]
linux
darwin
win32
[QtScriptTools::debugger_test]
linux
darwin
win32
# AttributeError: 'PySide2.QtQuick.QQuickItem' object has no attribute 'simpleFunction'
[QtQml::bug_451]
py2
py3
# Crashes with Python 2 on Windows
[QtQml::qqmlnetwork_test]
py2 win32
[QtQml::qquickitem_grabToImage]
darwin
[smart::smart_pointer]
py2
# PYSIDE-474
[QtWebEngineWidgets::pyside-474-qtwebengineview]
py2
py3
[QtCore::thread_signals_test]
win32
linux
darwin
[QtCore::qthread_prod_cons_test]
win32
linux
darwin
# PYSIDE-754
[QtWebEngineCore::web_engine_custom_scheme]
win32
linux
darwin
# In addition to a pre-existing windows failure,
# qtlocation/ac899dcc40bb3ad09307583fb7e6befd45a77b33 / QTBUG-66304 introduced
# a failure in 5.14
[QtPositioning::positioning]
win32
linux
darwin
# Open GL functions failures on macOS (2/2020)
[registry::existence_test]
darwin
build_scripts/ 0000775 0000000 0000000 00000000000 13766170131 0013731 5 ustar 00root root 0000000 0000000 build_scripts/__init__.py 0000664 0000000 0000000 00000003552 13766170131 0016047 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
build_scripts/build_scripts.pyproject 0000664 0000000 0000000 00000000670 13766170131 0020543 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "__init__.py", "config.py", "options.py", "qtinfo.py",
"setup_runner.py", "utils.py", "wheel_override.py", "wheel_utils.py",
"platforms/__init__.py", "platforms/linux.py",
"platforms/macos.py", "platforms/unix.py",
"platforms/windows_desktop.py",
"../setup.py",
"../coin_build_instructions.py", "../coin_test_instructions.py"]
}
build_scripts/config.py 0000664 0000000 0000000 00000040616 13766170131 0015557 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import os
import distutils.log as log
class Config(object):
def __init__(self):
# Constants
self._build_type_all = "all"
self._invocation_type_top_level = "top-level"
self._invocation_type_internal = "internal"
# The keyword arguments which will be given to setuptools.setup
self.setup_kwargs = {}
# The setup.py invocation type.
# top-level
# internal
self.invocation_type = None
# The type of the top-level build.
# all - build shiboken2 module, shiboken2-generator and PySide2
# modules
# shiboken2 - build only shiboken2 module
# shiboken2-generator - build only the shiboken2-generator
# pyside2 - build only PySide2 modules
self.build_type = None
# The internal build type, used for internal invocations of
# setup.py to build a specific module only.
self.internal_build_type = None
# Options that can be given to --build-type and
# --internal-build-type
self.shiboken_module_option_name = "shiboken2"
self.shiboken_generator_option_name = "shiboken2-generator"
self.pyside_option_name = "pyside2"
# Names to be passed to setuptools.setup() name key,
# so not package name, but rather project name as it appears
# in the wheel name and on PyPi.
self.shiboken_module_st_name = "shiboken2"
self.shiboken_generator_st_name = "shiboken2-generator"
self.pyside_st_name = "PySide2"
# Used by check_allowed_python_version to validate the
# interpreter version.
self.python_version_classifiers = [
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
]
self.setup_script_dir = None
def init_config(self, build_type=None, internal_build_type=None,
cmd_class_dict=None, package_version=None,
ext_modules=None, setup_script_dir=None,
quiet=False):
"""
Sets up the global singleton config which is used in many parts
of the setup process.
"""
# if --internal-build-type was passed, it means that this is a
# sub-invocation to build a specific package.
if internal_build_type:
self.set_is_internal_invocation()
self.set_internal_build_type(internal_build_type)
else:
self.set_is_top_level_invocation()
# --build-type was specified explicitly, so set it. Otherwise
# default to all.
if build_type:
self.build_type = build_type
else:
self.build_type = self._build_type_all
self.setup_script_dir = setup_script_dir
setup_kwargs = {}
setup_kwargs['long_description'] = self.get_long_description()
setup_kwargs['long_description_content_type'] = 'text/markdown'
setup_kwargs['keywords'] = 'Qt'
setup_kwargs['author'] = 'Qt for Python Team'
setup_kwargs['author_email'] = 'pyside@qt-project.org'
setup_kwargs['url'] = 'https://www.pyside.org'
setup_kwargs['download_url'] = 'https://download.qt.io/official_releases/QtForPython'
setup_kwargs['license'] = 'LGPL'
setup_kwargs['zip_safe'] = False
setup_kwargs['cmdclass'] = cmd_class_dict
setup_kwargs['version'] = package_version
setup_kwargs['python_requires'] = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.10"
if quiet:
# Tells distutils / setuptools to be quiet, and only print warnings or errors.
# Makes way less noise in the terminal when building.
setup_kwargs['verbose'] = 0
# Setting these two keys is still a bit of a discussion point.
# In general not setting them will allow using "build" and
# "bdist_wheel" just fine. What they do, is they specify to the
# setuptools.command.build_py command that certain pure python
# modules (.py files) exist in the specified package location,
# and that they should be copied over to the setuptools build
# dir.
# But it doesn't really make sense for us, because we copy all
# the necessary files to the build dir via prepare_packages()
# function anyway.
# If we don't set them, the build_py sub-command will be
# skipped, but the build command will still be executed, which
# is where we run cmake / make.
# The only plausible usage of it, is if we will implement a
# correctly functioning setup.py develop command (or bdist_egg).
# But currently that doesn't seem to work.
setup_kwargs['packages'] = self.get_setup_tools_packages_for_current_build()
setup_kwargs['package_dir'] = self.get_package_name_to_dir_path_mapping()
# Add a bogus extension module (will never be built here since
# we are overriding the build command to do it using cmake) so
# things like bdist_egg will know that there are extension
# modules and will name the dist with the full platform info.
setup_kwargs['ext_modules'] = ext_modules
common_classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Environment :: MacOS X',
'Environment :: X11 Applications :: Qt',
'Environment :: Win32 (MS Windows)',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
'License :: Other/Proprietary License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft',
'Operating System :: Microsoft :: Windows',
'Programming Language :: C++']
common_classifiers.extend(self.python_version_classifiers)
common_classifiers.extend([
'Topic :: Database',
'Topic :: Software Development',
'Topic :: Software Development :: Code Generators',
'Topic :: Software Development :: Libraries :: Application Frameworks',
'Topic :: Software Development :: User Interfaces',
'Topic :: Software Development :: Widget Sets'])
setup_kwargs['classifiers'] = common_classifiers
if self.internal_build_type == self.shiboken_module_option_name:
setup_kwargs['name'] = self.shiboken_module_st_name
setup_kwargs['description'] = "Python / C++ bindings helper module"
setup_kwargs['entry_points'] = {}
elif self.internal_build_type == self.shiboken_generator_option_name:
setup_kwargs['name'] = self.shiboken_generator_st_name
setup_kwargs['description'] = "Python / C++ bindings generator"
setup_kwargs['install_requires'] = ["{}=={}".format(self.shiboken_module_st_name, package_version)]
setup_kwargs['entry_points'] = {
'console_scripts': [
'shiboken2 = {}.scripts.shiboken_tool:main'.format(self.package_name()),
]
}
elif self.internal_build_type == self.pyside_option_name:
setup_kwargs['name'] = self.pyside_st_name
setup_kwargs['description'] = "Python bindings for the Qt cross-platform application and UI framework"
setup_kwargs['install_requires'] = ["{}=={}".format(self.shiboken_module_st_name, package_version)]
setup_kwargs['entry_points'] = {
'console_scripts': [
'pyside2-uic = {}.scripts.pyside_tool:uic'.format(self.package_name()),
'pyside2-rcc = {}.scripts.pyside_tool:rcc'.format(self.package_name()),
'pyside2-designer= {}.scripts.pyside_tool:designer'.format(self.package_name()),
'pyside2-lupdate = {}.scripts.pyside_tool:main'.format(self.package_name()),
]
}
self.setup_kwargs = setup_kwargs
def get_long_description(self):
readme_filename = 'README.md'
changes_filename = 'CHANGES.rst'
if self.is_internal_shiboken_module_build():
readme_filename = 'README.shiboken2.md'
elif self.is_internal_shiboken_generator_build():
readme_filename = 'README.shiboken2-generator.md'
elif self.is_internal_pyside_build():
readme_filename = 'README.pyside2.md'
content = ''
changes = ''
try:
with open(os.path.join(self.setup_script_dir, readme_filename)) as f:
readme = f.read()
except Exception as e:
log.error("Couldn't read contents of {}.".format(readme_filename))
raise
# Don't include CHANGES.rst for now, because we have not decided
# how to handle change files yet.
include_changes = False
if include_changes:
try:
with open(os.path.join(self.setup_script_dir, changes_filename)) as f:
changes = f.read()
except Exception as e:
log.error("Couldn't read contents of {}".format(changes_filename))
raise
content += readme
if changes:
content += "\n\n" + changes
return content
def package_name(self):
"""
Returns package name as it appears in Python's site-packages
directory.
Package names can only be delimited by underscores, and not by
dashes.
"""
if self.is_internal_shiboken_module_build():
return "shiboken2"
elif self.is_internal_shiboken_generator_build():
return "shiboken2_generator"
elif self.is_internal_pyside_build():
return "PySide2"
else:
return None
def get_setup_tools_packages_for_current_build(self):
"""
Returns a list of packages for setup tools to consider in the
build_py command, so that it can copy the pure python files.
Not really necessary because it's done in prepare_packages()
anyway.
This is really just to satisfy some checks in setuptools
build_py command, and if we ever properly implement the develop
command.
"""
if self.internal_build_type == self.pyside_option_name:
return [
config.package_name(),
]
elif self.internal_build_type == self.shiboken_module_option_name:
return [self.package_name()]
else:
return []
def get_package_name_to_dir_path_mapping(self):
"""
Used in setuptools.setup 'package_dir' argument to specify where
the actual module packages are located.
For example when building the shiboken module, setuptools will
expect to find the "shiboken2" module sources under
"sources/shiboken2/shibokenmodule".
This is really just to satisfy some checks in setuptools
build_py command, and if we ever properly implement the develop
command.
"""
if self.is_internal_shiboken_module_build():
return {
self.package_name(): "sources/shiboken2/shibokenmodule"
}
elif self.is_internal_shiboken_generator_build():
# This is left empty on purpose, because the shiboken
# generator doesn't have a python module for now.
return {}
elif self.is_internal_pyside_build():
return {
self.package_name(): "sources/pyside2/PySide2",
}
else:
return {}
def get_buildable_extensions(self):
"""
Used by PysideBuild.run to build the CMake projects.
:return: A list of directory names under the sources directory.
"""
if self.is_internal_shiboken_module_build() or self.is_internal_shiboken_generator_build():
return ['shiboken2']
elif self.is_internal_pyside_build():
return ['pyside2', 'pyside2-tools']
return None
def set_is_top_level_invocation(self):
self.invocation_type = self._invocation_type_top_level
def set_is_internal_invocation(self):
self.invocation_type = self._invocation_type_internal
def is_top_level_invocation(self):
return self.invocation_type == self._invocation_type_top_level
def is_internal_invocation(self):
return self.invocation_type == self._invocation_type_internal
def is_top_level_build_all(self):
return self.build_type == self._build_type_all
def is_top_level_build_shiboken_module(self):
return self.build_type == self.shiboken_module_option_name
def is_top_level_build_shiboken_generator(self):
return self.build_type == self.shiboken_generator_option_name
def is_top_level_build_pyside(self):
return self.build_type == self.pyside_option_name
def set_internal_build_type(self, internal_build_type):
self.internal_build_type = internal_build_type
def is_internal_shiboken_module_build(self):
return self.internal_build_type == self.shiboken_module_option_name
def is_internal_shiboken_generator_build(self):
return self.internal_build_type == self.shiboken_generator_option_name
def is_internal_pyside_build(self):
return self.internal_build_type == self.pyside_option_name
def is_internal_shiboken_generator_build_and_part_of_top_level_all(self):
"""
Used to skip certain build rules and output, when we know that
the CMake build of shiboken was already done as part of the
top-level "all" build when shiboken2-module was built.
"""
return self.is_internal_shiboken_generator_build() and self.is_top_level_build_all()
def get_allowed_top_level_build_values(self):
return [
self._build_type_all,
self.shiboken_module_option_name,
self.shiboken_generator_option_name,
self.pyside_option_name
]
def get_allowed_internal_build_values(self):
return [
self.shiboken_module_option_name,
self.shiboken_generator_option_name,
self.pyside_option_name
]
config = Config()
build_scripts/main.py 0000664 0000000 0000000 00000151017 13766170131 0015234 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
from distutils.version import LooseVersion
import os
import platform
import re
import sys
from textwrap import dedent
import time
from .config import config
from .utils import get_python_dict
from .options import DistUtilsCommandMixin, OPTION
from .wheel_utils import (get_package_version, get_qt_version,
get_package_timestamp, macos_plat_name,
macos_pyside_min_deployment_target)
setup_script_dir = os.getcwd()
build_scripts_dir = os.path.join(setup_script_dir, 'build_scripts')
setup_py_path = os.path.join(setup_script_dir, "setup.py")
start_time = int(time.time())
def elapsed():
return int(time.time()) - start_time
def get_setuptools_extension_modules():
# Setting py_limited_api on the extension is the "correct" thing
# to do, but it doesn't actually do anything, because we
# override build_ext. So this is just foolproofing for the
# future.
extension_args = ('QtCore', [])
extension_kwargs = {}
if OPTION["LIMITED_API"] == 'yes':
extension_kwargs['py_limited_api'] = True
extension_modules = [Extension(*extension_args, **extension_kwargs)]
return extension_modules
def _get_make(platform_arch, build_type):
"""Helper for retrieving the make command and CMake generator name"""
makespec = OPTION["MAKESPEC"]
if makespec == "make":
return ("make", "Unix Makefiles")
if makespec == "msvc":
nmake_path = find_executable("nmake")
if nmake_path is None or not os.path.exists(nmake_path):
log.info("nmake not found. Trying to initialize the MSVC env...")
init_msvc_env(platform_arch, build_type)
nmake_path = find_executable("nmake")
if not nmake_path or not os.path.exists(nmake_path):
raise DistutilsSetupError('"nmake" could not be found.')
if not OPTION["NO_JOM"]:
jom_path = find_executable("jom")
if jom_path:
log.info("jom was found in {}".format(jom_path))
return (jom_path, "NMake Makefiles JOM")
log.info("nmake was found in {}".format(nmake_path))
if OPTION["JOBS"]:
msg = "Option --jobs can only be used with 'jom' on Windows."
raise DistutilsSetupError(msg)
return (nmake_path, "NMake Makefiles")
if makespec == "mingw":
return ("mingw32-make", "mingw32-make")
if makespec == "ninja":
return ("ninja", "Ninja")
m = 'Invalid option --make-spec "{}".'.format(makespec)
raise DistutilsSetupError(m)
def get_make(platform_arch, build_type):
"""Retrieve the make command and CMake generator name"""
(make_path, make_generator) = _get_make(platform_arch, build_type)
if not os.path.isabs(make_path):
make_path = find_executable(make_path)
if not make_path or not os.path.exists(make_path):
raise DistutilsSetupError("You need the program '{}' on your system path to "
"compile PySide2.".format(make_path))
return (make_path, make_generator)
def _get_py_library_win(build_type, py_version, py_prefix, py_libdir,
py_include_dir):
"""Helper for finding the Python library on Windows"""
if py_include_dir is None or not os.path.exists(py_include_dir):
py_include_dir = os.path.join(py_prefix, "include")
if py_libdir is None or not os.path.exists(py_libdir):
# For virtual environments on Windows, the py_prefix will contain a
# path pointing to it, instead of the system Python installation path.
# Since INCLUDEPY contains a path to the system location, we use the
# same base directory to define the py_libdir variable.
py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
if not os.path.isdir(py_libdir):
raise DistutilsSetupError("Failed to locate the 'libs' directory")
dbg_postfix = "_d" if build_type == "Debug" else ""
if OPTION["MAKESPEC"] == "mingw":
static_lib_name = "libpython{}{}.a".format(
py_version.replace(".", ""), dbg_postfix)
return os.path.join(py_libdir, static_lib_name)
v = py_version.replace(".", "")
python_lib_name = "python{}{}.lib".format(v, dbg_postfix)
return os.path.join(py_libdir, python_lib_name)
def _get_py_library_unix(build_type, py_version, py_prefix, py_libdir,
py_include_dir):
"""Helper for finding the Python library on UNIX"""
if py_libdir is None or not os.path.exists(py_libdir):
py_libdir = os.path.join(py_prefix, "lib")
if py_include_dir is None or not os.path.exists(py_include_dir):
dir = "include/python{}".format(py_version)
py_include_dir = os.path.join(py_prefix, dir)
dbg_postfix = "_d" if build_type == "Debug" else ""
lib_exts = ['.so']
if sys.platform == 'darwin':
lib_exts.append('.dylib')
if sys.version_info[0] > 2:
lib_suff = getattr(sys, 'abiflags', None)
else: # Python 2
lib_suff = ''
lib_exts.append('.so.1')
# Suffix for OpenSuSE 13.01
lib_exts.append('.so.1.0')
# static library as last gasp
lib_exts.append('.a')
if sys.version_info[0] == 2 and dbg_postfix:
# For Python2 add a duplicate set of extensions combined with the
# dbg_postfix, so we test for both the debug version of the lib
# and the normal one. This allows a debug PySide2 to be built with a
# non-debug Python.
lib_exts = [dbg_postfix + e for e in lib_exts] + lib_exts
libs_tried = []
for lib_ext in lib_exts:
lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
py_library = os.path.join(py_libdir, lib_name)
if os.path.exists(py_library):
return py_library
libs_tried.append(py_library)
# At least on macOS 10.11, the system Python 2.6 does not include a
# symlink to the framework file disguised as a .dylib file, thus finding
# the library would fail. Manually check if a framework file "Python"
# exists in the Python framework bundle.
if sys.platform == 'darwin' and sys.version_info[:2] == (2, 6):
# These manipulations essentially transform
# /System/Library/Frameworks/Python.framework/Versions/2.6/lib
# to
# /System/Library/Frameworks/Python.framework/Versions/2.6/Python
possible_framework_path = os.path.realpath(os.path.join(py_libdir, '..'))
possible_framework_version = os.path.basename(possible_framework_path)
possible_framework_library = os.path.join(possible_framework_path, 'Python')
if (possible_framework_version == '2.6'
and os.path.exists(possible_framework_library)):
return possible_framework_library
libs_tried.append(possible_framework_library)
# Try to find shared libraries which have a multi arch
# suffix.
py_multiarch = get_config_var("MULTIARCH")
if py_multiarch:
try_py_libdir = os.path.join(py_libdir, py_multiarch)
libs_tried = []
for lib_ext in lib_exts:
lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
py_library = os.path.join(try_py_libdir, lib_name)
if os.path.exists(py_library):
return py_library
libs_tried.append(py_library)
m = "Failed to locate the Python library with {}".format(", ".join(libs_tried))
raise DistutilsSetupError(m)
def get_py_library(build_type, py_version, py_prefix, py_libdir, py_include_dir):
"""Find the Python library"""
if sys.platform == "win32":
py_library = _get_py_library_win(build_type, py_version, py_prefix,
py_libdir, py_include_dir)
else:
py_library = _get_py_library_unix(build_type, py_version, py_prefix,
py_libdir, py_include_dir)
if py_library.endswith('.a'):
# Python was compiled as a static library
log.error("Failed to locate a dynamic Python library, using {}".format(py_library))
return py_library
# Git submodules: ["submodule_name", "location_relative_to_sources_folder"]
submodules = [["pyside2-tools"]]
try:
import setuptools
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
from setuptools import Extension
from setuptools.command.install import install as _install
from setuptools.command.install_lib import install_lib as _install_lib
from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
from setuptools.command.develop import develop as _develop
from setuptools.command.build_py import build_py as _build_py
import distutils.log as log
from distutils.errors import DistutilsSetupError
from distutils.sysconfig import get_config_var
from distutils.sysconfig import get_python_lib
from distutils.spawn import find_executable
from distutils.command.build import build as _build
from distutils.command.build_ext import build_ext as _build_ext
from distutils.util import get_platform
from distutils.cmd import Command
from .qtinfo import QtInfo
from .utils import rmtree, detect_clang, copyfile, copydir, run_process_output, run_process
from .utils import update_env_path, init_msvc_env, filter_match
from .utils import macos_fix_rpaths_for_library
from .utils import linux_fix_rpaths_for_library
from .platforms.unix import prepare_packages_posix
from .platforms.windows_desktop import prepare_packages_win32
from .wheel_override import wheel_module_exists, get_bdist_wheel_override
def check_allowed_python_version():
"""
Make sure that setup.py is run with an allowed python version.
"""
import re
pattern = r'Programming Language :: Python :: (\d+)\.(\d+)'
supported = []
for line in config.python_version_classifiers:
found = re.search(pattern, line)
if found:
major = int(found.group(1))
minor = int(found.group(2))
supported.append((major, minor))
this_py = sys.version_info[:2]
if this_py not in supported:
print("Unsupported python version detected. Only these python versions are supported: {}"
.format(supported))
sys.exit(1)
qt_src_dir = ''
def is_debug_python():
return getattr(sys, "gettotalrefcount", None) is not None
# Return a prefix suitable for the _install/_build directory
def prefix():
virtual_env_name = os.environ.get('VIRTUAL_ENV', None)
if virtual_env_name is not None:
name = os.path.basename(virtual_env_name)
else:
name = "pyside"
name += str(sys.version_info[0])
if OPTION["DEBUG"]:
name += "d"
if is_debug_python():
name += "p"
if OPTION["LIMITED_API"] == "yes" and sys.version_info[0] == 3:
name += "a"
return name
# Initialize, pull and checkout submodules
def prepare_sub_modules():
print("Initializing submodules for PySide2 version: {}".format(
get_package_version()))
submodules_dir = os.path.join(setup_script_dir, "sources")
# Create list of [name, desired branch, absolute path, desired
# branch] and determine whether all submodules are present
need_init_sub_modules = False
for m in submodules:
module_name = m[0]
module_dir = m[1] if len(m) > 1 else ''
module_dir = os.path.join(submodules_dir, module_dir, module_name)
# Check for non-empty directory (repository checked out)
if not os.listdir(module_dir):
need_init_sub_modules = True
break
if need_init_sub_modules:
git_update_cmd = ["git", "submodule", "update", "--init"]
if run_process(git_update_cmd) != 0:
m = "Failed to initialize the git submodules: update --init failed"
raise DistutilsSetupError(m)
git_pull_cmd = ["git", "submodule", "foreach", "git", "fetch", "--all"]
if run_process(git_pull_cmd) != 0:
m = "Failed to initialize the git submodules: git fetch --all failed"
raise DistutilsSetupError(m)
else:
print("All submodules present.")
git_update_cmd = ["git", "submodule", "update"]
if run_process(git_update_cmd) != 0:
m = "Failed to checkout the correct git submodules SHA1s."
raise DistutilsSetupError(m)
def prepare_build():
if (os.path.isdir(".git") and not OPTION["IGNOREGIT"] and not OPTION["ONLYPACKAGE"]
and not OPTION["REUSE_BUILD"]):
prepare_sub_modules()
# Clean up temp build folder.
for n in ["build"]:
d = os.path.join(setup_script_dir, n)
if os.path.isdir(d):
log.info("Removing {}".format(d))
try:
rmtree(d)
except Exception as e:
print('***** problem removing "{}"'.format(d))
print('ignored error: {}'.format(e))
# locate Qt sources for the documentation
if OPTION["QT_SRC"] is None:
install_prefix = QtInfo().prefix_dir
if install_prefix:
global qt_src_dir
# In-source, developer build
if install_prefix.endswith("qtbase"):
qt_src_dir = install_prefix
else: # SDK: Use 'Src' directory
qt_src_dir = os.path.join(os.path.dirname(install_prefix), 'Src', 'qtbase')
class PysideInstall(_install, DistUtilsCommandMixin):
user_options = _install.user_options + DistUtilsCommandMixin.mixin_user_options
def __init__(self, *args, **kwargs):
_install.__init__(self, *args, **kwargs)
DistUtilsCommandMixin.__init__(self)
def initialize_options(self):
_install.initialize_options(self)
if sys.platform == 'darwin':
# Because we change the plat_name to include a correct
# deployment target on macOS distutils thinks we are
# cross-compiling, and throws an exception when trying to
# execute setup.py install. The check looks like this
# if self.warn_dir and build_plat != get_platform():
# raise DistutilsPlatformError("Can't install when "
# "cross-compiling")
# Obviously get_platform will return the old deployment
# target. The fix is to disable the warn_dir flag, which
# was created for bdist_* derived classes to override, for
# similar cases.
self.warn_dir = False
def finalize_options(self):
DistUtilsCommandMixin.mixin_finalize_options(self)
_install.finalize_options(self)
def run(self):
_install.run(self)
print('--- Install completed ({}s)'.format(elapsed()))
class PysideDevelop(_develop):
def __init__(self, *args, **kwargs):
_develop.__init__(self, *args, **kwargs)
def run(self):
self.run_command("build")
_develop.run(self)
class PysideBdistEgg(_bdist_egg):
def __init__(self, *args, **kwargs):
_bdist_egg.__init__(self, *args, **kwargs)
def run(self):
self.run_command("build")
_bdist_egg.run(self)
class PysideBuildExt(_build_ext):
def __init__(self, *args, **kwargs):
_build_ext.__init__(self, *args, **kwargs)
def run(self):
pass
class PysideBuildPy(_build_py):
def __init__(self, *args, **kwargs):
_build_py.__init__(self, *args, **kwargs)
# _install_lib is reimplemented to preserve
# symlinks when distutils / setuptools copy files to various
# directories from the setup tools build dir to the install dir.
class PysideInstallLib(_install_lib):
def __init__(self, *args, **kwargs):
_install_lib.__init__(self, *args, **kwargs)
def install(self):
"""
Installs files from build/xxx directory into final
site-packages/PySide2 directory.
"""
if os.path.isdir(self.build_dir):
# Using our own copydir makes sure to preserve symlinks.
outfiles = copydir(os.path.abspath(self.build_dir), os.path.abspath(self.install_dir))
else:
self.warn("'{}' does not exist -- no Python modules to install".format(self.build_dir))
return
return outfiles
class PysideBuild(_build, DistUtilsCommandMixin):
user_options = _build.user_options + DistUtilsCommandMixin.mixin_user_options
def __init__(self, *args, **kwargs):
_build.__init__(self, *args, **kwargs)
DistUtilsCommandMixin.__init__(self)
def finalize_options(self):
os_name_backup = os.name
DistUtilsCommandMixin.mixin_finalize_options(self)
if sys.platform == 'darwin':
self.plat_name = macos_plat_name()
# This is a hack to circumvent the dubious check in
# distutils.commands.build -> finalize_options, which only
# allows setting the plat_name for windows NT.
# That is not the case for the wheel module though (which
# does allow setting plat_name), so we circumvent by faking
# the os name when finalizing the options, and then
# restoring the original os name.
os.name = "nt"
_build.finalize_options(self)
if sys.platform == 'darwin':
os.name = os_name_backup
def initialize_options(self):
_build.initialize_options(self)
self.make_path = None
self.make_generator = None
self.script_dir = None
self.sources_dir = None
self.build_dir = None
self.install_dir = None
self.py_executable = None
self.py_include_dir = None
self.py_library = None
self.py_version = None
self.py_arch = None
self.build_type = "Release"
self.qtinfo = None
self.build_tests = False
def run(self):
prepare_build()
platform_arch = platform.architecture()[0]
log.info("Python architecture is {}".format(platform_arch))
self.py_arch = platform_arch[:-3]
build_type = "Debug" if OPTION["DEBUG"] else "Release"
if OPTION["RELWITHDEBINFO"]:
build_type = 'RelWithDebInfo'
# Check env
make_path = None
make_generator = None
if not OPTION["ONLYPACKAGE"]:
(make_path, make_generator) = get_make(platform_arch, build_type)
# Prepare parameters
py_executable = sys.executable
py_version = "{}.{}".format(sys.version_info[0], sys.version_info[1])
py_include_dir = get_config_var("INCLUDEPY")
py_libdir = get_config_var("LIBDIR")
py_prefix = get_config_var("prefix")
if not py_prefix or not os.path.exists(py_prefix):
py_prefix = sys.prefix
self.py_prefix = py_prefix
if sys.platform == "win32":
py_scripts_dir = os.path.join(py_prefix, "Scripts")
else:
py_scripts_dir = os.path.join(py_prefix, "bin")
self.py_scripts_dir = py_scripts_dir
self.qtinfo = QtInfo()
qt_dir = os.path.dirname(OPTION["QMAKE"])
qt_version = get_qt_version()
# Update the PATH environment variable
additional_paths = [self.py_scripts_dir, qt_dir]
# Add Clang to path for Windows.
# Revisit once Clang is bundled with Qt.
if (sys.platform == "win32"
and LooseVersion(self.qtinfo.version) >= LooseVersion("5.7.0")):
clang_dir = detect_clang()
if clang_dir[0]:
clangBinDir = os.path.join(clang_dir[0], 'bin')
if clangBinDir not in os.environ.get('PATH'):
log.info("Adding {} as detected by {} to PATH".format(clangBinDir,
clang_dir[1]))
additional_paths.append(clangBinDir)
else:
raise DistutilsSetupError("Failed to detect Clang when checking "
"LLVM_INSTALL_DIR, CLANG_INSTALL_DIR, llvm-config")
update_env_path(additional_paths)
# Used for test blacklists and registry test.
self.build_classifiers = "py{}-qt{}-{}-{}".format(py_version, qt_version,
platform.architecture()[0],
build_type.lower())
if OPTION["SHORTER_PATHS"]:
build_name = "p{}".format(py_version)
else:
build_name = self.build_classifiers
script_dir = setup_script_dir
sources_dir = os.path.join(script_dir, "sources")
build_dir = os.path.join(script_dir, prefix() + "_build", "{}".format(build_name))
install_dir = os.path.join(script_dir, prefix() + "_install", "{}".format(build_name))
self.make_path = make_path
self.make_generator = make_generator
self.script_dir = script_dir
self.st_build_dir = os.path.join(self.script_dir, self.build_lib)
self.sources_dir = sources_dir
self.build_dir = build_dir
self.install_dir = install_dir
self.py_executable = py_executable
self.py_include_dir = py_include_dir
self.py_library = get_py_library(build_type, py_version, py_prefix,
py_libdir, py_include_dir)
self.py_version = py_version
self.build_type = build_type
self.site_packages_dir = get_python_lib(1, 0, prefix=install_dir)
self.build_tests = OPTION["BUILDTESTS"]
# Save the shiboken build dir path for clang deployment
# purposes.
self.shiboken_build_dir = os.path.join(self.build_dir, "shiboken2")
self.log_pre_build_info()
# Prepare folders
if not os.path.exists(self.sources_dir):
log.info("Creating sources folder {}...".format(self.sources_dir))
os.makedirs(self.sources_dir)
if not os.path.exists(self.build_dir):
log.info("Creating build folder {}...".format(self.build_dir))
os.makedirs(self.build_dir)
if not os.path.exists(self.install_dir):
log.info("Creating install folder {}...".format(self.install_dir))
os.makedirs(self.install_dir)
if (not OPTION["ONLYPACKAGE"]
and not config.is_internal_shiboken_generator_build_and_part_of_top_level_all()):
# Build extensions
for ext in config.get_buildable_extensions():
self.build_extension(ext)
if OPTION["BUILDTESTS"]:
# we record the latest successful build and note the
# build directory for supporting the tests.
timestamp = time.strftime('%Y-%m-%d_%H%M%S')
build_history = os.path.join(setup_script_dir, 'build_history')
unique_dir = os.path.join(build_history, timestamp)
os.makedirs(unique_dir)
fpath = os.path.join(unique_dir, 'build_dir.txt')
with open(fpath, 'w') as f:
print(build_dir, file=f)
print(self.build_classifiers, file=f)
log.info("Created {}".format(build_history))
if not OPTION["SKIP_PACKAGING"]:
# Build patchelf if needed
self.build_patchelf()
# Prepare packages
self.prepare_packages()
# Build packages
_build.run(self)
else:
log.info("Skipped preparing and building packages.")
print('--- Build completed ({}s)'.format(elapsed()))
def log_pre_build_info(self):
if config.is_internal_shiboken_generator_build_and_part_of_top_level_all():
return
setuptools_install_prefix = get_python_lib(1)
if OPTION["FINAL_INSTALL_PREFIX"]:
setuptools_install_prefix = OPTION["FINAL_INSTALL_PREFIX"]
log.info("=" * 30)
log.info("Package version: {}".format(get_package_version()))
log.info("Build type: {}".format(self.build_type))
log.info("Build tests: {}".format(self.build_tests))
log.info("-" * 3)
log.info("Make path: {}".format(self.make_path))
log.info("Make generator: {}".format(self.make_generator))
log.info("Make jobs: {}".format(OPTION["JOBS"]))
log.info("-" * 3)
log.info("setup.py directory: {}".format(self.script_dir))
log.info("Build scripts directory: {}".format(build_scripts_dir))
log.info("Sources directory: {}".format(self.sources_dir))
log.info(dedent("""
Building {st_package_name} will create and touch directories
in the following order:
make build directory (py*_build/*/*) ->
make install directory (py*_install/*/*) ->
setuptools build directory (build/*/*) ->
setuptools install directory
(usually path-installed-python/lib/python*/site-packages/*)
""").format(st_package_name=config.package_name()))
log.info("make build directory: {}".format(self.build_dir))
log.info("make install directory: {}".format(self.install_dir))
log.info("setuptools build directory: {}".format(self.st_build_dir))
log.info("setuptools install directory: {}".format(setuptools_install_prefix))
log.info(dedent("""
make-installed site-packages directory: {}
(only relevant for copying files from 'make install directory'
to 'setuptools build directory'
""").format(
self.site_packages_dir))
log.info("-" * 3)
log.info("Python executable: {}".format(self.py_executable))
log.info("Python includes: {}".format(self.py_include_dir))
log.info("Python library: {}".format(self.py_library))
log.info("Python prefix: {}".format(self.py_prefix))
log.info("Python scripts: {}".format(self.py_scripts_dir))
log.info("-" * 3)
log.info("Qt qmake: {}".format(self.qtinfo.qmake_command))
log.info("Qt version: {}".format(self.qtinfo.version))
log.info("Qt bins: {}".format(self.qtinfo.bins_dir))
log.info("Qt docs: {}".format(self.qtinfo.docs_dir))
log.info("Qt plugins: {}".format(self.qtinfo.plugins_dir))
log.info("-" * 3)
if sys.platform == 'win32':
log.info("OpenSSL dll directory: {}".format(OPTION["OPENSSL"]))
if sys.platform == 'darwin':
pyside_macos_deployment_target = (
macos_pyside_min_deployment_target()
)
log.info("MACOSX_DEPLOYMENT_TARGET set to: {}".format(
pyside_macos_deployment_target))
log.info("=" * 30)
def build_patchelf(self):
if not sys.platform.startswith('linux'):
return
self._patchelf_path = find_executable('patchelf')
if self._patchelf_path:
if not os.path.isabs(self._patchelf_path):
self._patchelf_path = os.path.join(os.getcwd(), self._patchelf_path)
log.info("Using {} ...".format(self._patchelf_path))
return
log.info("Building patchelf...")
module_src_dir = os.path.join(self.sources_dir, "patchelf")
build_cmd = ["g++", "{}/patchelf.cc".format(module_src_dir), "-o", "patchelf"]
if run_process(build_cmd) != 0:
raise DistutilsSetupError("Error building patchelf")
self._patchelf_path = os.path.join(self.script_dir, "patchelf")
def build_extension(self, extension):
# calculate the subrepos folder name
log.info("Building module {}...".format(extension))
# Prepare folders
os.chdir(self.build_dir)
module_build_dir = os.path.join(self.build_dir, extension)
skipflag_file = "{} -skip".format(module_build_dir)
if os.path.exists(skipflag_file):
log.info("Skipping {} because {} exists".format(extension, skipflag_file))
return
module_build_exists = os.path.exists(module_build_dir)
if module_build_exists:
if not OPTION["REUSE_BUILD"]:
log.info("Deleting module build folder {}...".format(module_build_dir))
try:
rmtree(module_build_dir)
except Exception as e:
print('***** problem removing "{}"'.format(module_build_dir))
print('ignored error: {}'.format(e))
else:
log.info("Reusing module build folder {}...".format(module_build_dir))
if not os.path.exists(module_build_dir):
log.info("Creating module build folder {}...".format(module_build_dir))
os.makedirs(module_build_dir)
os.chdir(module_build_dir)
module_src_dir = os.path.join(self.sources_dir, extension)
# Build module
cmake_cmd = [OPTION["CMAKE"]]
if OPTION["QUIET"]:
# Pass a special custom option, to allow printing a lot less information when doing
# a quiet build.
cmake_cmd.append('-DQUIET_BUILD=1')
if self.make_generator == "Unix Makefiles":
# Hide progress messages for each built source file.
# Doesn't seem to work if set within the cmake files themselves.
cmake_cmd.append('-DCMAKE_RULE_MESSAGES=0')
cmake_cmd += [
"-G", self.make_generator,
"-DBUILD_TESTS={}".format(self.build_tests),
"-DQt5Help_DIR={}".format(self.qtinfo.docs_dir),
"-DCMAKE_BUILD_TYPE={}".format(self.build_type),
"-DCMAKE_INSTALL_PREFIX={}".format(self.install_dir),
module_src_dir
]
cmake_cmd.append("-DPYTHON_EXECUTABLE={}".format(self.py_executable))
cmake_cmd.append("-DPYTHON_INCLUDE_DIR={}".format(self.py_include_dir))
cmake_cmd.append("-DPYTHON_LIBRARY={}".format(self.py_library))
# If a custom shiboken cmake config directory path was provided, pass it to CMake.
if OPTION["SHIBOKEN_CONFIG_DIR"] and config.is_internal_pyside_build():
if os.path.exists(OPTION["SHIBOKEN_CONFIG_DIR"]):
log.info("Using custom provided shiboken2 installation: {}"
.format(OPTION["SHIBOKEN_CONFIG_DIR"]))
cmake_cmd.append("-DShiboken2_DIR={}".format(OPTION["SHIBOKEN_CONFIG_DIR"]))
else:
log.info("Custom provided shiboken2 installation not found. Path given: {}"
.format(OPTION["SHIBOKEN_CONFIG_DIR"]))
if OPTION["MODULE_SUBSET"]:
module_sub_set = ''
for m in OPTION["MODULE_SUBSET"].split(','):
if m.startswith('Qt'):
m = m[2:]
if module_sub_set:
module_sub_set += ';'
module_sub_set += m
cmake_cmd.append("-DMODULES={}".format(module_sub_set))
if OPTION["SKIP_MODULES"]:
skip_modules = ''
for m in OPTION["SKIP_MODULES"].split(','):
if m.startswith('Qt'):
m = m[2:]
if skip_modules:
skip_modules += ';'
skip_modules += m
cmake_cmd.append("-DSKIP_MODULES={}".format(skip_modules))
# Add source location for generating documentation
cmake_src_dir = OPTION["QT_SRC"] if OPTION["QT_SRC"] else qt_src_dir
cmake_cmd.append("-DQT_SRC_DIR={}".format(cmake_src_dir))
log.info("Qt Source dir: {}".format(cmake_src_dir))
if self.build_type.lower() == 'debug':
cmake_cmd.append("-DPYTHON_DEBUG_LIBRARY={}".format(
self.py_library))
if OPTION["LIMITED_API"] == "yes":
cmake_cmd.append("-DFORCE_LIMITED_API=yes")
elif OPTION["LIMITED_API"] == "no":
cmake_cmd.append("-DFORCE_LIMITED_API=no")
elif not OPTION["LIMITED_API"]:
pass
else:
raise DistutilsSetupError("option limited-api must be 'yes' or 'no' "
"(default yes if applicable, i.e. python version >= 3.5)")
if OPTION["VERBOSE_BUILD"]:
cmake_cmd.append("-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON")
if OPTION["SANITIZE_ADDRESS"]:
# Some simple sanity checking. Only use at your own risk.
if (sys.platform.startswith('linux')
or sys.platform.startswith('darwin')):
cmake_cmd.append("-DSANITIZE_ADDRESS=ON")
else:
raise DistutilsSetupError("Address sanitizer can only be used on Linux and macOS.")
if extension.lower() == "pyside2":
pyside_qt_conf_prefix = ''
if OPTION["QT_CONF_PREFIX"]:
pyside_qt_conf_prefix = OPTION["QT_CONF_PREFIX"]
else:
if OPTION["STANDALONE"]:
pyside_qt_conf_prefix = '"Qt"'
if sys.platform == 'win32':
pyside_qt_conf_prefix = '"."'
cmake_cmd.append("-DPYSIDE_QT_CONF_PREFIX={}".format(
pyside_qt_conf_prefix))
# Pass package version to CMake, so this string can be
# embedded into _config.py file.
package_version = get_package_version()
cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_VERSION={}".format(package_version))
# In case if this is a snapshot build, also pass the
# timestamp as a separate value, because it is the only
# version component that is actually generated by setup.py.
timestamp = ''
if OPTION["SNAPSHOT_BUILD"]:
timestamp = get_package_timestamp()
cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_TIMESTAMP={}".format(timestamp))
if extension.lower() in ["shiboken2", "pyside2-tools"]:
cmake_cmd.append("-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=yes")
if sys.version_info[0] > 2:
cmake_cmd.append("-DUSE_PYTHON_VERSION=3.3")
if sys.platform == 'darwin':
if OPTION["MACOS_ARCH"]:
# also tell cmake which architecture to use
cmake_cmd.append("-DCMAKE_OSX_ARCHITECTURES:STRING={}".format(OPTION["MACOS_ARCH"]))
if OPTION["MACOS_USE_LIBCPP"]:
# Explicitly link the libc++ standard library (useful
# for macOS deployment targets lower than 10.9).
# This is not on by default, because most libraries and
# executables on macOS <= 10.8 are linked to libstdc++,
# and mixing standard libraries can lead to crashes.
# On macOS >= 10.9 with a similar minimum deployment
# target, libc++ is linked in implicitly, thus the
# option is a no-op in those cases.
cmake_cmd.append("-DOSX_USE_LIBCPP=ON")
if OPTION["MACOS_SYSROOT"]:
cmake_cmd.append("-DCMAKE_OSX_SYSROOT={}".format(
OPTION["MACOS_SYSROOT"]))
else:
latest_sdk_path = run_process_output(['xcrun', '--sdk', 'macosx',
'--show-sdk-path'])
if latest_sdk_path:
latest_sdk_path = latest_sdk_path[0]
cmake_cmd.append("-DCMAKE_OSX_SYSROOT={}".format(
latest_sdk_path))
# Set macOS minimum deployment target (version).
# This is required so that calling
# run_process -> distutils.spawn()
# does not set its own minimum deployment target
# environment variable which is based on the python
# interpreter sysconfig value.
# Doing so could break the detected clang include paths
# for example.
deployment_target = macos_pyside_min_deployment_target()
cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format(deployment_target))
os.environ['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
if OPTION["DOC_BUILD_ONLINE"]:
log.info("Output format will be HTML")
cmake_cmd.append("-DDOC_OUTPUT_FORMAT=html")
else:
log.info("Output format will be qthelp")
cmake_cmd.append("-DDOC_OUTPUT_FORMAT=qthelp")
# Build the whole documentation (rst + API) by default
cmake_cmd.append("-DFULLDOCSBUILD=1")
if not OPTION["SKIP_CMAKE"]:
log.info("Configuring module {} ({})...".format(extension, module_src_dir))
if run_process(cmake_cmd) != 0:
raise DistutilsSetupError("Error configuring {}".format(extension))
else:
log.info("Reusing old configuration for module {} ({})...".format(
extension, module_src_dir))
log.info("-- Compiling module {}...".format(extension))
cmd_make = [self.make_path]
if OPTION["JOBS"]:
cmd_make.append(OPTION["JOBS"])
if run_process(cmd_make) != 0:
raise DistutilsSetupError("Error compiling {}".format(extension))
if not OPTION["SKIP_DOCS"]:
if extension.lower() == "shiboken2":
try:
# Check if sphinx is installed to proceed.
import sphinx
log.info("Generating Shiboken documentation")
if run_process([self.make_path, "doc"]) != 0:
raise DistutilsSetupError("Error generating documentation "
"for {}".format(extension))
except ImportError:
log.info("Sphinx not found, skipping documentation build")
else:
log.info("Skipped documentation generation")
if not OPTION["SKIP_MAKE_INSTALL"]:
log.info("Installing module {}...".format(extension))
# Need to wait a second, so installed file timestamps are
# older than build file timestamps.
# See https://gitlab.kitware.com/cmake/cmake/issues/16155
# for issue details.
if sys.platform == 'darwin':
log.info("Waiting 1 second, to ensure installation is successful...")
time.sleep(1)
# ninja: error: unknown target 'install/fast'
target = 'install/fast' if self.make_generator != 'Ninja' else 'install'
if run_process([self.make_path, target]) != 0:
raise DistutilsSetupError("Error pseudo installing {}".format(
extension))
else:
log.info("Skipped installing module {}".format(extension))
os.chdir(self.script_dir)
def prepare_packages(self):
"""
This will copy all relevant files from the various locations in the "cmake install dir",
to the setup tools build dir (which is read from self.build_lib provided by distutils).
After that setuptools.command.build_py is smart enough to copy everything
from the build dir to the install dir (the virtualenv site-packages for example).
"""
try:
log.info("\nPreparing setup tools build directory.\n")
vars = {
"site_packages_dir": self.site_packages_dir,
"sources_dir": self.sources_dir,
"install_dir": self.install_dir,
"build_dir": self.build_dir,
"script_dir": self.script_dir,
"st_build_dir": self.st_build_dir,
"cmake_package_name": config.package_name(),
"st_package_name": config.package_name(),
"ssl_libs_dir": OPTION["OPENSSL"],
"py_version": self.py_version,
"qt_version": self.qtinfo.version,
"qt_bin_dir": self.qtinfo.bins_dir,
"qt_doc_dir": self.qtinfo.docs_dir,
"qt_lib_dir": self.qtinfo.libs_dir,
"qt_lib_execs_dir": self.qtinfo.lib_execs_dir,
"qt_plugins_dir": self.qtinfo.plugins_dir,
"qt_prefix_dir": self.qtinfo.prefix_dir,
"qt_translations_dir": self.qtinfo.translations_dir,
"qt_qml_dir": self.qtinfo.qml_dir,
"target_arch": self.py_arch,
}
# Needed for correct file installation in generator build
# case.
if config.is_internal_shiboken_generator_build():
vars['cmake_package_name'] = config.shiboken_module_option_name
os.chdir(self.script_dir)
if sys.platform == "win32":
vars['dbg_postfix'] = OPTION["DEBUG"] and "_d" or ""
return prepare_packages_win32(self, vars)
else:
return prepare_packages_posix(self, vars)
except IOError as e:
print('setup.py/prepare_packages: ', e)
raise
def qt_is_framework_build(self):
if os.path.isdir(self.qtinfo.headers_dir + "/../lib/QtCore.framework"):
return True
return False
def get_built_pyside_config(self, vars):
# Get config that contains list of built modules, and
# SOVERSIONs of the built libraries.
st_build_dir = vars['st_build_dir']
config_path = os.path.join(st_build_dir, config.package_name(), "_config.py")
temp_config = get_python_dict(config_path)
if 'built_modules' not in temp_config:
temp_config['built_modules'] = []
return temp_config
def is_webengine_built(self, built_modules):
return ('WebEngineWidgets' in built_modules
or 'WebEngineCore' in built_modules
or 'WebEngine' in built_modules)
def prepare_standalone_clang(self, is_win=False):
"""
Copies the libclang library to the shiboken2-generator
package so that the shiboken executable works.
"""
log.info('Finding path to the libclang shared library.')
cmake_cmd = [
OPTION["CMAKE"],
"-L", # Lists variables
"-N", # Just inspects the cache (faster)
"--build", # Specifies the build dir
self.shiboken_build_dir
]
out = run_process_output(cmake_cmd)
lines = [s.strip() for s in out]
pattern = re.compile(r"CLANG_LIBRARY:FILEPATH=(.+)$")
clang_lib_path = None
for line in lines:
match = pattern.search(line)
if match:
clang_lib_path = match.group(1)
break
if not clang_lib_path:
raise RuntimeError("Could not find the location of the libclang "
"library inside the CMake cache file.")
if is_win:
# clang_lib_path points to the static import library
# (lib/libclang.lib), whereas we want to copy the shared
# library (bin/libclang.dll).
clang_lib_path = re.sub(r'lib/libclang.lib$',
'bin/libclang.dll',
clang_lib_path)
else:
# shiboken2 links against libclang.so.6 or a similarly
# named library.
# If the linked against library is a symlink, resolve
# the symlink once (but not all the way to the real
# file) on Linux and macOS,
# so that we get the path to the "SO version" symlink
# (the one used as the install name in the shared library
# dependency section).
# E.g. On Linux libclang.so -> libclang.so.6 ->
# libclang.so.6.0.
# "libclang.so.6" is the name we want for the copied file.
if os.path.islink(clang_lib_path):
link_target = os.readlink(clang_lib_path)
if os.path.isabs(link_target):
clang_lib_path = link_target
else:
# link_target is relative, transform to absolute.
clang_lib_path = os.path.join(os.path.dirname(clang_lib_path), link_target)
clang_lib_path = os.path.abspath(clang_lib_path)
# The destination will be the shiboken package folder.
vars = {}
vars['st_build_dir'] = self.st_build_dir
vars['st_package_name'] = config.package_name()
destination_dir = "{st_build_dir}/{st_package_name}".format(**vars)
if os.path.exists(clang_lib_path):
basename = os.path.basename(clang_lib_path)
log.info('Copying libclang shared library {} to the package folder as {}.'.format(
clang_lib_path, basename))
destination_path = os.path.join(destination_dir, basename)
# Need to modify permissions in case file is not writable
# (a reinstall would cause a permission denied error).
copyfile(clang_lib_path,
destination_path,
force_copy_symlink=True,
make_writable_by_owner=True)
else:
raise RuntimeError("Error copying libclang library "
"from {} to {}. ".format(clang_lib_path, destination_dir))
def update_rpath(self, package_path, executables):
if sys.platform.startswith('linux'):
pyside_libs = [lib for lib in os.listdir(
package_path) if filter_match(lib, ["*.so", "*.so.*"])]
def rpath_cmd(srcpath):
final_rpath = ''
# Command line rpath option takes precedence over
# automatically added one.
if OPTION["RPATH_VALUES"]:
final_rpath = OPTION["RPATH_VALUES"]
else:
# Add rpath values pointing to $ORIGIN and the
# installed qt lib directory.
final_rpath = self.qtinfo.libs_dir
if OPTION["STANDALONE"]:
final_rpath = "$ORIGIN/Qt/lib"
override = OPTION["STANDALONE"]
linux_fix_rpaths_for_library(self._patchelf_path, srcpath, final_rpath,
override=override)
elif sys.platform == 'darwin':
pyside_libs = [lib for lib in os.listdir(
package_path) if filter_match(lib, ["*.so", "*.dylib"])]
def rpath_cmd(srcpath):
final_rpath = ''
# Command line rpath option takes precedence over
# automatically added one.
if OPTION["RPATH_VALUES"]:
final_rpath = OPTION["RPATH_VALUES"]
else:
if OPTION["STANDALONE"]:
final_rpath = "@loader_path/Qt/lib"
else:
final_rpath = self.qtinfo.libs_dir
macos_fix_rpaths_for_library(srcpath, final_rpath)
else:
raise RuntimeError('Not configured for platform {}'.format(sys.platform))
pyside_libs.extend(executables)
# Update rpath in PySide2 libs
for srcname in pyside_libs:
srcpath = os.path.join(package_path, srcname)
if os.path.isdir(srcpath) or os.path.islink(srcpath):
continue
if not os.path.exists(srcpath):
continue
rpath_cmd(srcpath)
log.info("Patched rpath to '$ORIGIN/' (Linux) or "
"updated rpath (OS/X) in {}.".format(srcpath))
class PysideRstDocs(Command, DistUtilsCommandMixin):
description = "Build .rst documentation only"
user_options = DistUtilsCommandMixin.mixin_user_options
def initialize_options(self):
DistUtilsCommandMixin.__init__(self)
log.info("-- This build process will not include the API documentation."
"API documentation requires a full build of pyside/shiboken.")
self.skip = False
if config.is_internal_shiboken_generator_build():
self.skip = True
if not self.skip:
self.name = config.package_name().lower()
self.doc_dir = os.path.join(config.setup_script_dir, "sources")
self.doc_dir = os.path.join(self.doc_dir, self.name)
self.doc_dir = os.path.join(self.doc_dir, "doc")
try:
# Check if sphinx is installed to proceed.
import sphinx
if self.name == "shiboken2":
log.info("-- Generating Shiboken documentation")
log.info("-- Documentation directory: 'html/pyside2/shiboken2/'")
elif self.name == "pyside2":
log.info("-- Generating PySide documentation")
log.info("-- Documentation directory: 'html/pyside2/'")
except ImportError:
raise DistutilsSetupError("Sphinx not found - aborting")
self.html_dir = "html"
# creating directories html/pyside2/shiboken2
try:
if not os.path.isdir(self.html_dir):
os.mkdir(self.html_dir)
if self.name == "shiboken2":
out_pyside = os.path.join(self.html_dir, "pyside2")
if not os.path.isdir(out_pyside):
os.mkdir(out_pyside)
out_shiboken = os.path.join(out_pyside, "shiboken2")
if not os.path.isdir(out_shiboken):
os.mkdir(out_shiboken)
self.out_dir = out_shiboken
# We know that on the shiboken step, we already created the
# 'pyside2' directory
elif self.name == "pyside2":
self.out_dir = os.path.join(self.html_dir, "pyside2")
except:
raise DistutilsSetupError("Error while creating directories for {}".format(self.doc_dir))
def run(self):
if not self.skip:
cmake_cmd = [OPTION["CMAKE"]]
cmake_cmd += [
"-S", self.doc_dir,
"-B", self.out_dir,
"-DDOC_OUTPUT_FORMAT=html",
"-DFULLDOCSBUILD=0",
]
if run_process(cmake_cmd) != 0:
raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
if self.name == "pyside2":
self.sphinx_src = os.path.join(self.out_dir, "rst")
elif self.name == "shiboken2":
self.sphinx_src = self.out_dir
sphinx_cmd = ["sphinx-build", "-b", "html", "-c", self.sphinx_src,
self.doc_dir, self.out_dir]
if run_process(sphinx_cmd) != 0:
raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
# Last message
if not self.skip and self.name == "pyside2":
log.info("-- The documentation was built. Check html/pyside2/index.html")
def finalize_options(self):
DistUtilsCommandMixin.mixin_finalize_options(self)
cmd_class_dict = {
'build': PysideBuild,
'build_py': PysideBuildPy,
'build_ext': PysideBuildExt,
'bdist_egg': PysideBdistEgg,
'develop': PysideDevelop,
'install': PysideInstall,
'install_lib': PysideInstallLib,
'build_rst_docs': PysideRstDocs,
}
if wheel_module_exists:
pyside_bdist_wheel = get_bdist_wheel_override()
if pyside_bdist_wheel:
cmd_class_dict['bdist_wheel'] = pyside_bdist_wheel
build_scripts/options.py 0000664 0000000 0000000 00000031637 13766170131 0016010 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import distutils.log as log
from distutils.spawn import find_executable
import sys
import os
import warnings
from .qtinfo import QtInfo
_AVAILABLE_MKSPECS = ["msvc", "mingw", "ninja"] if sys.platform == "win32" else ["make", "ninja"]
# Global options not which are not part of the commands
ADDITIONAL_OPTIONS = """
Additional options:
--limited-api Use Limited API [yes/no]
---macos-use-libc++ Use libc++ on macOS
--snapshot-build Snapshot build
--package-timestamp Package Timestamp
"""
def _warn_multiple_option(option):
warnings.warn('Option "{}" occurs multiple times on the command line.'.format(option))
def _warn_deprecated_option(option, replacement=None):
w = 'Option "{}" is deprecated and may be removed in a future release.'.format(option)
if replacement:
w = '{}\nUse "{}" instead.'.format(w, replacement)
warnings.warn(w)
class Options(object):
def __init__(self):
# Dictionary containing values of all the possible options.
self.dict = {}
def has_option(self, name, remove=True):
""" Returns True if argument '--name' was passed on the command
line. """
option = '--{}'.format(name)
count = sys.argv.count(option)
remove_count = count
if not remove and count > 0:
remove_count -= 1
for i in range(remove_count):
sys.argv.remove(option)
if count > 1:
_warn_multiple_option(option)
return count > 0
def option_value(self, name, short_option_name=None, remove=True):
"""
Returns the value of a command line option or environment
variable.
:param name: The name of the command line option or environment
variable.
:param remove: Whether the option and its value should be
removed from sys.argv. Useful when there's a need to query for
the value and also pass it along to setuptools for example.
:return: Either the option value or None.
"""
option = '--' + name
short_option = '-' + short_option_name if short_option_name else None
single_option_prefix = option + '='
value = None
for index in reversed(range(len(sys.argv))):
arg = sys.argv[index]
if arg == option or short_option and arg == short_option:
if value:
_warn_multiple_option(option)
else:
if index + 1 >= len(sys.argv):
raise RuntimeError("The option {} requires a value".format(option))
value = sys.argv[index + 1]
if remove:
sys.argv[index:index + 2] = []
elif arg.startswith(single_option_prefix):
if value:
_warn_multiple_option(option)
else:
value = arg[len(single_option_prefix):]
if remove:
sys.argv[index:index + 1] = []
if value is None:
value = os.getenv(name.upper().replace('-', '_'))
self.dict[name] = value
return value
options = Options()
def has_option(*args, **kwargs):
return options.has_option(*args, **kwargs)
def option_value(*args, **kwargs):
return options.option_value(*args, **kwargs)
def _jobs_option_value():
"""Option value for parallel builds."""
value = option_value('parallel', short_option_name='j')
if value:
return '-j' + value if not value.startswith('-j') else value
return ''
# Declare options which need to be known when instantiating the DistUtils
# commands.
OPTION = {
"BUILD_TYPE": option_value("build-type"),
"INTERNAL_BUILD_TYPE": option_value("internal-build-type"),
# number of parallel build jobs
"JOBS": _jobs_option_value(),
# Legacy, not used any more.
"JOM": has_option('jom'),
"MACOS_USE_LIBCPP": has_option("macos-use-libc++"),
"QUIET": has_option('quiet', remove=False),
"SNAPSHOT_BUILD": has_option("snapshot-build"),
"LIMITED_API": option_value("limited-api"),
"PACKAGE_TIMESTAMP": option_value("package-timestamp"),
# This is used automatically by distutils.command.install object, to
# specify the final installation location.
"FINAL_INSTALL_PREFIX": option_value("prefix", remove=False)
# This is used to identify the template for doc builds
}
_deprecated_option_jobs = option_value('jobs')
if _deprecated_option_jobs:
_warn_deprecated_option('jobs', 'parallel')
OPTION["JOBS"] = _deprecated_option_jobs
class DistUtilsCommandMixin(object):
"""Mixin for the DistUtils build/install commands handling the options."""
_finalized = False
mixin_user_options = [
('debug', None, 'Build with debug information'),
('relwithdebinfo', None, 'Build in release mode with debug information'),
('only-package', None, 'Package only'),
('standalone', None, 'Standalone build'),
('ignore-git', None, 'Do update subrepositories'),
('skip-docs', None, 'Skip documentation build'),
('no-examples', None, 'Do not build examples'),
('no-jom', None, 'Do not use jom (MSVC)'),
('build-tests', None, 'Build tests'),
('use-xvfb', None, 'Use Xvfb for testing'),
('reuse-build', None, 'Reuse existing build'),
('skip-cmake', None, 'Skip CMake step'),
('skip-make-install', None, 'Skip install step'),
('skip-packaging', None, 'Skip packaging step'),
('verbose-build', None, 'Verbose build'),
('sanitize-address', None, 'Build with address sanitizer'),
('shorter-paths', None, 'Use shorter paths'),
('doc-build-online', None, 'Build online documentation'),
('qmake=', None, 'Path to qmake'),
('qt=', None, 'Qt version'),
('cmake=', None, 'Path to CMake'),
('openssl=', None, 'Path to OpenSSL libraries'),
('shiboken-config-dir=', None, 'shiboken configuration directory'),
('make-spec=', None, 'Qt make-spec'),
('macos-arch=', None, 'macOS architecture'),
('macos-sysroot=', None, 'macOS sysroot'),
('macos-deployment-target=', None, 'macOS deployment target'),
('skip-modules=', None, 'Qt modules to be skipped'),
('module-subset=', None, 'Qt modules to be built'),
('rpath=', None, 'RPATH'),
('qt-conf-prefix=', None, 'Qt configuration prefix'),
('qt-src-dir=', None, 'Qt source directory')]
def __init__(self):
self.debug = False
self.relwithdebinfo = False
self.only_package = False
self.standalone = False
self.ignore_git = False
self.skip_docs = False
self.no_examples = False
self.no_jom = False
self.build_tests = False
self.use_xvfb = False
self.reuse_build = False
self.skip_cmake = False
self.skip_make_install = False
self.skip_packaging = False
self.verbose_build = False
self.sanitize_address = False
self.snapshot_build = False
self.shorter_paths = False
self.doc_build_online = False
self.qmake = None
self.qt = '5'
self.cmake = None
self.openssl = None
self.shiboken_config_dir = None
self.make_spec = None
self.macos_arch = None
self.macos_sysroot = None
self.macos_deployment_target = None
self.skip_modules = None
self.module_subset = None
self.rpath = None
self.qt_conf_prefix = None
self.qt_src_dir = None
def mixin_finalize_options(self):
# Bail out on 2nd call to mixin_finalize_options() since that is the
# build command following the install command when invoking
# setup.py install
if not DistUtilsCommandMixin._finalized:
DistUtilsCommandMixin._finalized = True
self._do_finalize()
def _do_finalize(self):
if not self._determine_defaults_and_check():
sys.exit(-1)
OPTION['DEBUG'] = self.debug
OPTION['RELWITHDEBINFO'] = self.relwithdebinfo
OPTION['ONLYPACKAGE'] = self.only_package
OPTION['STANDALONE'] = self.standalone
OPTION['IGNOREGIT'] = self.ignore_git
OPTION['SKIP_DOCS'] = self.skip_docs
OPTION['NOEXAMPLES'] = self.no_examples
OPTION['BUILDTESTS'] = self.build_tests
OPTION['NO_JOM'] = self.no_jom
OPTION['XVFB'] = self.use_xvfb
OPTION['REUSE_BUILD'] = self.reuse_build
OPTION['SKIP_CMAKE'] = self.skip_cmake
OPTION['SKIP_MAKE_INSTALL'] = self.skip_make_install
OPTION['SKIP_PACKAGING'] = self.skip_packaging
OPTION['VERBOSE_BUILD'] = self.verbose_build
if self.verbose_build:
log.set_verbosity(1)
OPTION['SANITIZE_ADDRESS'] = self.sanitize_address
OPTION['SHORTER_PATHS'] = self.shorter_paths
OPTION['DOC_BUILD_ONLINE'] = self.doc_build_online
# make qtinfo.py independent of relative paths.
qmake_abs_path = os.path.abspath(self.qmake)
OPTION['QMAKE'] = qmake_abs_path
OPTION['QT_VERSION'] = self.qt
QtInfo().setup(qmake_abs_path, self.qt)
OPTION['CMAKE'] = os.path.abspath(self.cmake)
OPTION['OPENSSL'] = self.openssl
OPTION['SHIBOKEN_CONFIG_DIR'] = self.shiboken_config_dir
OPTION['MAKESPEC'] = self.make_spec
OPTION['MACOS_ARCH'] = self.macos_arch
OPTION['MACOS_SYSROOT'] = self.macos_sysroot
OPTION['MACOS_DEPLOYMENT_TARGET'] = self.macos_deployment_target
OPTION['SKIP_MODULES'] = self.skip_modules
OPTION['MODULE_SUBSET'] = self.module_subset
OPTION['RPATH_VALUES'] = self.rpath
OPTION['QT_CONF_PREFIX'] = self.qt_conf_prefix
OPTION['QT_SRC'] = self.qt_src_dir
def _determine_defaults_and_check(self):
if not self.cmake:
self.cmake = find_executable("cmake")
if not self.cmake:
print("cmake could not be found.")
return False
if not os.path.exists(self.cmake):
print("'{}' does not exist.".format(self.cmake))
return False
if not self.qmake:
self.qmake = find_executable("qmake")
if not self.qmake:
self.qmake = find_executable("qmake-qt5")
if not self.qmake:
print("qmake could not be found.")
return False
if not os.path.exists(self.qmake):
print("'{}' does not exist.".format(self.qmake))
return False
if not self.make_spec:
self.make_spec = _AVAILABLE_MKSPECS[0]
if self.make_spec not in _AVAILABLE_MKSPECS:
print('Invalid option --make-spec "{}". Available values are {}'.format(OPTION["MAKESPEC"],
_AVAILABLE_MKSPECS))
return False
if OPTION["JOBS"] and sys.platform == 'win32' and self.no_jom:
print("Option --jobs can only be used with jom on Windows.")
return False
return True
build_scripts/platforms/ 0000775 0000000 0000000 00000000000 13766170131 0015740 5 ustar 00root root 0000000 0000000 build_scripts/platforms/__init__.py 0000664 0000000 0000000 00000003552 13766170131 0020056 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
build_scripts/platforms/linux.py 0000664 0000000 0000000 00000013673 13766170131 0017463 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from ..utils import (copydir, copyfile, copy_icu_libs, find_files_using_glob,
linux_set_rpaths, linux_run_read_elf, linux_get_rpaths,
rpaths_has_origin)
from ..config import config
def prepare_standalone_package_linux(self, vars):
built_modules = vars['built_modules']
constrain_modules = None
copy_plugins = True
copy_qml = True
copy_translations = True
copy_qt_conf = True
should_copy_icu_libs = True
if config.is_internal_shiboken_generator_build():
constrain_modules = ["Core", "Network", "Xml", "XmlPatterns"]
copy_plugins = False
copy_qml = False
copy_translations = False
copy_qt_conf = False
should_copy_icu_libs = False
# /lib/* -> /{st_package_name}/Qt/lib
destination_lib_dir = "{st_build_dir}/{st_package_name}/Qt/lib"
accepted_modules = ['libQt5*.so.?']
if constrain_modules:
accepted_modules = ["libQt5" + module + "*.so.?" for module in constrain_modules]
accepted_modules.append("libicu*.so.??")
copydir("{qt_lib_dir}", destination_lib_dir,
filter=accepted_modules,
recursive=False, vars=vars, force_copy_symlinks=True)
if should_copy_icu_libs:
# Check if ICU libraries were copied over to the destination
# Qt libdir.
resolved_destination_lib_dir = destination_lib_dir.format(**vars)
maybe_icu_libs = find_files_using_glob(resolved_destination_lib_dir, "libicu*")
# If no ICU libraries are present in the Qt libdir (like when
# Qt is built against system ICU, or in the Coin CI where ICU
# libs are in a different directory) try to find out / resolve
# which ICU libs are used by QtCore (if used at all) using a
# custom written ldd, and copy the ICU libs to the Pyside Qt
# dir if necessary. We choose the QtCore lib to inspect, by
# checking which QtCore library the shiboken2 executable uses.
if not maybe_icu_libs:
copy_icu_libs(self._patchelf_path, resolved_destination_lib_dir)
# Patching designer to use the Qt libraries provided in the wheel
if config.is_internal_pyside_build():
designer_path = "{st_build_dir}/{st_package_name}/designer".format(**vars)
rpaths = linux_get_rpaths(designer_path)
if not rpaths or not rpaths_has_origin(rpaths):
rpaths.insert(0, '$ORIGIN/../lib')
new_rpaths_string = ":".join(rpaths)
linux_set_rpaths(self._patchelf_path, designer_path, new_rpaths_string)
if self.is_webengine_built(built_modules):
copydir("{qt_lib_execs_dir}",
"{st_build_dir}/{st_package_name}/Qt/libexec",
filter=None,
recursive=False,
vars=vars)
copydir("{qt_prefix_dir}/resources",
"{st_build_dir}/{st_package_name}/Qt/resources",
filter=None,
recursive=False,
vars=vars)
if copy_plugins:
# /plugins/* -> /{st_package_name}/Qt/plugins
copydir("{qt_plugins_dir}",
"{st_build_dir}/{st_package_name}/Qt/plugins",
filter=["*.so"],
recursive=True,
vars=vars)
if copy_qml:
# /qml/* -> /{st_package_name}/Qt/qml
copydir("{qt_qml_dir}",
"{st_build_dir}/{st_package_name}/Qt/qml",
filter=None,
force=False,
recursive=True,
ignore=["*.so.debug"],
vars=vars)
if copy_translations:
# /translations/* ->
# /{st_package_name}/Qt/translations
copydir("{qt_translations_dir}",
"{st_build_dir}/{st_package_name}/Qt/translations",
filter=["*.qm", "*.pak"],
force=False,
vars=vars)
if copy_qt_conf:
# Copy the qt.conf file to libexec.
copyfile(
"{build_dir}/pyside2/{st_package_name}/qt.conf",
"{st_build_dir}/{st_package_name}/Qt/libexec",
vars=vars)
build_scripts/platforms/macos.py 0000664 0000000 0000000 00000021472 13766170131 0017422 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import fnmatch
import os
from ..utils import copydir, copyfile, macos_fix_rpaths_for_library, macos_add_rpath
from ..config import config
def prepare_standalone_package_macos(self, vars):
built_modules = vars['built_modules']
constrain_modules = None
copy_plugins = True
copy_qml = True
copy_translations = True
copy_qt_conf = True
if config.is_internal_shiboken_generator_build():
constrain_modules = ["Core", "Network", "Xml", "XmlPatterns"]
constrain_frameworks = ['Qt' + name + '.framework' for name in constrain_modules]
copy_plugins = False
copy_qml = False
copy_translations = False
copy_qt_conf = False
# Directory filter for skipping unnecessary files.
def general_dir_filter(dir_name, parent_full_path, dir_full_path):
if fnmatch.fnmatch(dir_name, "*.dSYM"):
return False
return True
# Filter out debug plugins and qml plugins in the
# debug_and_release config.
no_copy_debug = True
def file_variant_filter(file_name, file_full_path):
if self.qtinfo.build_type != 'debug_and_release':
return True
if file_name.endswith('_debug.dylib') and no_copy_debug:
return False
return True
# Patching designer to use the Qt libraries provided in the wheel
if config.is_internal_pyside_build():
designer_bundle = "{st_build_dir}/{st_package_name}/Designer.app".format(**vars)
designer_binary = "{}/Contents/MacOS/Designer".format(designer_bundle)
rpath = "@loader_path/../../../Qt/lib"
macos_add_rpath(rpath, designer_binary)
# /lib/* -> /{st_package_name}/Qt/lib
if self.qt_is_framework_build():
def framework_dir_filter(dir_name, parent_full_path, dir_full_path):
if '.framework' in dir_name:
if (dir_name.startswith('QtWebEngine')
and not self.is_webengine_built(built_modules)):
return False
if constrain_modules and dir_name not in constrain_frameworks:
return False
if dir_name in ['Headers', 'fonts']:
return False
if dir_full_path.endswith('Versions/Current'):
return False
if dir_full_path.endswith('Versions/5/Resources'):
return False
if dir_full_path.endswith('Versions/5/Helpers'):
return False
return general_dir_filter(dir_name, parent_full_path, dir_full_path)
# Filter out debug frameworks in the
# debug_and_release config.
no_copy_debug = True
def framework_variant_filter(file_name, file_full_path):
if self.qtinfo.build_type != 'debug_and_release':
return True
dir_path = os.path.dirname(file_full_path)
in_framework = dir_path.endswith("Versions/5")
if file_name.endswith('_debug') and in_framework and no_copy_debug:
return False
return True
copydir("{qt_lib_dir}", "{st_build_dir}/{st_package_name}/Qt/lib",
recursive=True, vars=vars,
ignore=["*.la", "*.a", "*.cmake", "*.pc", "*.prl"],
dir_filter_function=framework_dir_filter,
file_filter_function=framework_variant_filter)
# Fix rpath for WebEngine process executable. The already
# present rpath does not work because it assumes a symlink
# from Versions/5/Helpers, thus adding two more levels of
# directory hierarchy.
if self.is_webengine_built(built_modules):
qt_lib_path = "{st_build_dir}/{st_package_name}/Qt/lib".format(**vars)
bundle = "QtWebEngineCore.framework/Helpers/"
bundle += "QtWebEngineProcess.app"
binary = "Contents/MacOS/QtWebEngineProcess"
webengine_process_path = os.path.join(bundle, binary)
final_path = os.path.join(qt_lib_path, webengine_process_path)
rpath = "@loader_path/../../../../../"
macos_fix_rpaths_for_library(final_path, rpath)
else:
ignored_modules = []
if not self.is_webengine_built(built_modules):
ignored_modules.extend(['libQt5WebEngine*.dylib'])
if 'WebKit' not in built_modules:
ignored_modules.extend(['libQt5WebKit*.dylib'])
accepted_modules = ['libQt5*.5.dylib']
if constrain_modules:
accepted_modules = ["libQt5" + module + "*.5.dylib" for module in constrain_modules]
copydir("{qt_lib_dir}",
"{st_build_dir}/{st_package_name}/Qt/lib",
filter=accepted_modules,
ignore=ignored_modules,
file_filter_function=file_variant_filter,
recursive=True, vars=vars, force_copy_symlinks=True)
if self.is_webengine_built(built_modules):
copydir("{qt_lib_execs_dir}",
"{st_build_dir}/{st_package_name}/Qt/libexec",
filter=None,
recursive=False,
vars=vars)
copydir("{qt_prefix_dir}/resources",
"{st_build_dir}/{st_package_name}/Qt/resources",
filter=None,
recursive=False,
vars=vars)
# Fix rpath for WebEngine process executable.
qt_libexec_path = "{st_build_dir}/{st_package_name}/Qt/libexec".format(**vars)
binary = "QtWebEngineProcess"
final_path = os.path.join(qt_libexec_path, binary)
rpath = "@loader_path/../lib"
macos_fix_rpaths_for_library(final_path, rpath)
if copy_qt_conf:
# Copy the qt.conf file to libexec.
copyfile(
"{build_dir}/pyside2/{st_package_name}/qt.conf",
"{st_build_dir}/{st_package_name}/Qt/libexec",
vars=vars)
if copy_plugins:
# /plugins/* -> /{st_package_name}/Qt/plugins
copydir("{qt_plugins_dir}",
"{st_build_dir}/{st_package_name}/Qt/plugins",
filter=["*.dylib"],
recursive=True,
dir_filter_function=general_dir_filter,
file_filter_function=file_variant_filter,
vars=vars)
if copy_qml:
# /qml/* -> /{st_package_name}/Qt/qml
copydir("{qt_qml_dir}",
"{st_build_dir}/{st_package_name}/Qt/qml",
filter=None,
recursive=True,
force=False,
dir_filter_function=general_dir_filter,
file_filter_function=file_variant_filter,
vars=vars)
if copy_translations:
# /translations/* ->
# /{st_package_name}/Qt/translations
copydir("{qt_translations_dir}",
"{st_build_dir}/{st_package_name}/Qt/translations",
filter=["*.qm", "*.pak"],
force=False,
vars=vars)
build_scripts/platforms/unix.py 0000664 0000000 0000000 00000021507 13766170131 0017302 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import os
import sys
import fnmatch
from .linux import prepare_standalone_package_linux
from .macos import prepare_standalone_package_macos
from ..config import config
from ..options import OPTION
from ..utils import copydir, copyfile, makefile
from ..utils import regenerate_qt_resources
def prepare_packages_posix(self, vars):
executables = []
# /lib/site-packages/{st_package_name}/* ->
# /{st_package_name}
# This copies the module .so/.dylib files and various .py files
# (__init__, config, git version, etc.)
copydir(
"{site_packages_dir}/{st_package_name}",
"{st_build_dir}/{st_package_name}",
vars=vars)
generated_config = self.get_built_pyside_config(vars)
def adjusted_lib_name(name, version):
postfix = ''
if sys.platform.startswith('linux'):
postfix = '.so.' + version
elif sys.platform == 'darwin':
postfix = '.' + version + '.dylib'
return name + postfix
if config.is_internal_shiboken_module_build():
# /shiboken2/doc/html/* ->
# /{st_package_name}/docs/shiboken2
copydir(
"{build_dir}/shiboken2/doc/html",
"{st_build_dir}/{st_package_name}/docs/shiboken2",
force=False, vars=vars)
# /lib/lib* -> {st_package_name}/
copydir(
"{install_dir}/lib/",
"{st_build_dir}/{st_package_name}",
filter=[
adjusted_lib_name("libshiboken*",
generated_config['shiboken_library_soversion']),
],
recursive=False, vars=vars, force_copy_symlinks=True)
if config.is_internal_shiboken_generator_build():
# /bin/* -> {st_package_name}/
executables.extend(copydir(
"{install_dir}/bin/",
"{st_build_dir}/{st_package_name}",
filter=[
"shiboken2",
],
recursive=False, vars=vars))
# Used to create scripts directory.
makefile(
"{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py",
vars=vars)
# For setting up setuptools entry points.
copyfile(
"{install_dir}/bin/shiboken_tool.py",
"{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py",
force=False, vars=vars)
if config.is_internal_shiboken_generator_build() or config.is_internal_pyside_build():
# /include/* -> /{st_package_name}/include
copydir(
"{install_dir}/include/{cmake_package_name}",
"{st_build_dir}/{st_package_name}/include",
vars=vars)
if config.is_internal_pyside_build():
makefile(
"{st_build_dir}/{st_package_name}/scripts/__init__.py",
vars=vars)
# For setting up setuptools entry points
copyfile(
"{install_dir}/bin/pyside_tool.py",
"{st_build_dir}/{st_package_name}/scripts/pyside_tool.py",
force=False, vars=vars)
# /bin/* -> {st_package_name}/
executables.extend(copydir(
"{install_dir}/bin/",
"{st_build_dir}/{st_package_name}",
filter=[
"pyside2-lupdate",
"uic",
"rcc",
],
recursive=False, vars=vars))
# Copying designer
if sys.platform == "darwin":
executables.extend(copydir(
"{install_dir}/bin/Designer.app",
"{st_build_dir}/{st_package_name}/Designer.app",
filter=None, recursive=True,
force=False, vars=vars))
else:
copyfile(
"{install_dir}/bin/designer",
"{st_build_dir}/{st_package_name}/designer",
force=False, vars=vars)
# /lib/lib* -> {st_package_name}/
copydir(
"{install_dir}/lib/",
"{st_build_dir}/{st_package_name}",
filter=[
adjusted_lib_name("libpyside*",
generated_config['pyside_library_soversion']),
],
recursive=False, vars=vars, force_copy_symlinks=True)
# /share/{st_package_name}/typesystems/* ->
# /{st_package_name}/typesystems
copydir(
"{install_dir}/share/{st_package_name}/typesystems",
"{st_build_dir}/{st_package_name}/typesystems",
vars=vars)
# /share/{st_package_name}/glue/* ->
# /{st_package_name}/glue
copydir(
"{install_dir}/share/{st_package_name}/glue",
"{st_build_dir}/{st_package_name}/glue",
vars=vars)
# /pyside2/{st_package_name}/support/* ->
# /{st_package_name}/support/*
copydir(
"{build_dir}/pyside2/{st_package_name}/support",
"{st_build_dir}/{st_package_name}/support",
vars=vars)
# /pyside2/{st_package_name}/*.pyi ->
# /{st_package_name}/*.pyi
copydir(
"{build_dir}/pyside2/{st_package_name}",
"{st_build_dir}/{st_package_name}",
filter=["*.pyi", "py.typed"],
vars=vars)
if not OPTION["NOEXAMPLES"]:
def pycache_dir_filter(dir_name, parent_full_path, dir_full_path):
if fnmatch.fnmatch(dir_name, "__pycache__"):
return False
return True
# examples/* -> /{st_package_name}/examples
copydir(os.path.join(self.script_dir, "examples"),
"{st_build_dir}/{st_package_name}/examples",
force=False, vars=vars, dir_filter_function=pycache_dir_filter)
# Re-generate examples Qt resource files for Python 3
# compatibility
if sys.version_info[0] == 3:
examples_path = "{st_build_dir}/{st_package_name}/examples".format(**vars)
pyside_rcc_path = "{install_dir}/bin/rcc".format(**vars)
pyside_rcc_options = ['-g', 'python']
regenerate_qt_resources(examples_path, pyside_rcc_path, pyside_rcc_options)
# Copy Qt libs to package
if OPTION["STANDALONE"]:
if config.is_internal_pyside_build() or config.is_internal_shiboken_generator_build():
vars['built_modules'] = generated_config['built_modules']
if sys.platform == 'darwin':
prepare_standalone_package_macos(self, vars)
else:
prepare_standalone_package_linux(self, vars)
if config.is_internal_shiboken_generator_build():
# Copy over clang before rpath patching.
self.prepare_standalone_clang(is_win=False)
# Update rpath to $ORIGIN
if sys.platform.startswith('linux') or sys.platform.startswith('darwin'):
rpath_path = "{st_build_dir}/{st_package_name}".format(**vars)
self.update_rpath(rpath_path, executables)
build_scripts/platforms/windows_desktop.py 0000664 0000000 0000000 00000043351 13766170131 0021543 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import functools
import os
import sys
import fnmatch
from ..config import config
from ..options import OPTION
from ..utils import copydir, copyfile, makefile
from ..utils import regenerate_qt_resources, filter_match
from ..utils import download_and_extract_7z
def prepare_packages_win32(self, vars):
# For now, debug symbols will not be shipped into the package.
copy_pdbs = False
pdbs = []
if (self.debug or self.build_type == 'RelWithDebInfo') and copy_pdbs:
pdbs = ['*.pdb']
# /lib/site-packages/{st_package_name}/* ->
# /{st_package_name}
# This copies the module .pyd files and various .py files
# (__init__, config, git version, etc.)
copydir(
"{site_packages_dir}/{st_package_name}",
"{st_build_dir}/{st_package_name}",
vars=vars)
if config.is_internal_shiboken_module_build():
# /shiboken2/doc/html/* ->
# /{st_package_name}/docs/shiboken2
copydir(
"{build_dir}/shiboken2/doc/html",
"{st_build_dir}/{st_package_name}/docs/shiboken2",
force=False, vars=vars)
# /bin/*.dll -> {st_package_name}/
copydir(
"{install_dir}/bin/",
"{st_build_dir}/{st_package_name}",
filter=["shiboken*.dll"],
recursive=False, vars=vars)
# /lib/*.lib -> {st_package_name}/
copydir(
"{install_dir}/lib/",
"{st_build_dir}/{st_package_name}",
filter=["shiboken*.lib"],
recursive=False, vars=vars)
# @TODO: Fix this .pdb file not to overwrite release
# {shibokengenerator}.pdb file.
# Task-number: PYSIDE-615
copydir(
"{build_dir}/shiboken2/shibokenmodule",
"{st_build_dir}/{st_package_name}",
filter=pdbs,
recursive=False, vars=vars)
# pdb files for libshiboken and libpyside
copydir(
"{build_dir}/shiboken2/libshiboken",
"{st_build_dir}/{st_package_name}",
filter=pdbs,
recursive=False, vars=vars)
if config.is_internal_shiboken_generator_build():
# /bin/*.dll -> {st_package_name}/
copydir(
"{install_dir}/bin/",
"{st_build_dir}/{st_package_name}",
filter=["shiboken*.exe"],
recursive=False, vars=vars)
# Used to create scripts directory.
makefile(
"{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py",
vars=vars)
# For setting up setuptools entry points.
copyfile(
"{install_dir}/bin/shiboken_tool.py",
"{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py",
force=False, vars=vars)
# @TODO: Fix this .pdb file not to overwrite release
# {shibokenmodule}.pdb file.
# Task-number: PYSIDE-615
copydir(
"{build_dir}/shiboken2/generator",
"{st_build_dir}/{st_package_name}",
filter=pdbs,
recursive=False, vars=vars)
if config.is_internal_shiboken_generator_build() or config.is_internal_pyside_build():
# /include/* -> /{st_package_name}/include
copydir(
"{install_dir}/include/{cmake_package_name}",
"{st_build_dir}/{st_package_name}/include",
vars=vars)
if config.is_internal_pyside_build():
# /pyside2/{st_package_name}/*.pdb ->
# /{st_package_name}
copydir(
"{build_dir}/pyside2/{st_package_name}",
"{st_build_dir}/{st_package_name}",
filter=pdbs,
recursive=False, vars=vars)
makefile(
"{st_build_dir}/{st_package_name}/scripts/__init__.py",
vars=vars)
# For setting up setuptools entry points
copyfile(
"{install_dir}/bin/pyside_tool.py",
"{st_build_dir}/{st_package_name}/scripts/pyside_tool.py",
force=False, vars=vars)
# /bin/*.exe,*.dll -> {st_package_name}/
copydir(
"{install_dir}/bin/",
"{st_build_dir}/{st_package_name}",
filter=["pyside*.exe", "pyside*.dll", "uic.exe", "rcc.exe", "designer.exe"],
recursive=False, vars=vars)
# /lib/*.lib -> {st_package_name}/
copydir(
"{install_dir}/lib/",
"{st_build_dir}/{st_package_name}",
filter=["pyside*.lib"],
recursive=False, vars=vars)
# /share/{st_package_name}/typesystems/* ->
# /{st_package_name}/typesystems
copydir(
"{install_dir}/share/{st_package_name}/typesystems",
"{st_build_dir}/{st_package_name}/typesystems",
vars=vars)
# /share/{st_package_name}/glue/* ->
# /{st_package_name}/glue
copydir(
"{install_dir}/share/{st_package_name}/glue",
"{st_build_dir}/{st_package_name}/glue",
vars=vars)
# /pyside2/{st_package_name}/support/* ->
# /{st_package_name}/support/*
copydir(
"{build_dir}/pyside2/{st_package_name}/support",
"{st_build_dir}/{st_package_name}/support",
vars=vars)
# /pyside2/{st_package_name}/*.pyi ->
# /{st_package_name}/*.pyi
copydir(
"{build_dir}/pyside2/{st_package_name}",
"{st_build_dir}/{st_package_name}",
filter=["*.pyi", "py.typed"],
vars=vars)
copydir(
"{build_dir}/pyside2/libpyside",
"{st_build_dir}/{st_package_name}",
filter=pdbs,
recursive=False, vars=vars)
if not OPTION["NOEXAMPLES"]:
def pycache_dir_filter(dir_name, parent_full_path, dir_full_path):
if fnmatch.fnmatch(dir_name, "__pycache__"):
return False
return True
# examples/* -> /{st_package_name}/examples
copydir(os.path.join(self.script_dir, "examples"),
"{st_build_dir}/{st_package_name}/examples",
force=False, vars=vars, dir_filter_function=pycache_dir_filter)
# Re-generate examples Qt resource files for Python 3
# compatibility
if sys.version_info[0] == 3:
examples_path = "{st_build_dir}/{st_package_name}/examples".format(
**vars)
pyside_rcc_path = "{install_dir}/bin/rcc.exe".format(
**vars)
pyside_rcc_options = ['-g', 'python']
regenerate_qt_resources(examples_path, pyside_rcc_path, pyside_rcc_options)
if vars['ssl_libs_dir']:
# /* -> /{st_package_name}/openssl
copydir("{ssl_libs_dir}", "{st_build_dir}/{st_package_name}/openssl",
filter=[
"libeay32.dll",
"ssleay32.dll"],
force=False, vars=vars)
if config.is_internal_shiboken_module_build():
# The C++ std library dlls need to be packaged with the
# shiboken module, because libshiboken uses C++ code.
copy_msvc_redist_files(vars, "{build_dir}/msvc_redist".format(**vars))
if config.is_internal_pyside_build() or config.is_internal_shiboken_generator_build():
copy_qt_artifacts(self, copy_pdbs, vars)
copy_msvc_redist_files(vars, "{build_dir}/msvc_redist".format(**vars))
def copy_msvc_redist_files(vars, redist_target_path):
# MSVC redistributable file list.
msvc_redist = [
"concrt140.dll",
"msvcp140.dll",
"ucrtbase.dll",
"vcamp140.dll",
"vccorlib140.dll",
"vcomp140.dll",
"vcruntime140.dll",
"vcruntime140_1.dll",
"msvcp140_1.dll",
"msvcp140_2.dll",
"msvcp140_codecvt_ids.dll"
]
# Make a directory where the files should be extracted.
if not os.path.exists(redist_target_path):
os.makedirs(redist_target_path)
# Extract Qt dependency dlls when building on Qt CI.
in_coin = os.environ.get('COIN_LAUNCH_PARAMETERS', None)
if in_coin is not None:
redist_url = "http://download.qt.io/development_releases/prebuilt/vcredist/"
zip_file = "pyside_qt_deps_64_2019.7z"
if "{target_arch}".format(**vars) == "32":
zip_file = "pyside_qt_deps_32_2019.7z"
download_and_extract_7z(redist_url + zip_file, redist_target_path)
else:
print("Qt dependency DLLs (MSVC redist) will not be downloaded and extracted.")
copydir(redist_target_path,
"{st_build_dir}/{st_package_name}",
filter=msvc_redist, recursive=False, vars=vars)
def copy_qt_artifacts(self, copy_pdbs, vars):
built_modules = self.get_built_pyside_config(vars)['built_modules']
constrain_modules = None
copy_plugins = True
copy_qml = True
copy_translations = True
copy_qt_conf = True
copy_qt_permanent_artifacts = True
copy_msvc_redist = False
copy_clang = False
if config.is_internal_shiboken_generator_build():
constrain_modules = ["Core", "Network", "Xml", "XmlPatterns"]
copy_plugins = False
copy_qml = False
copy_translations = False
copy_qt_conf = False
copy_qt_permanent_artifacts = False
copy_msvc_redist = True
copy_clang = True
# /bin/*.dll and Qt *.exe -> /{st_package_name}
qt_artifacts_permanent = [
"opengl*.dll",
"d3d*.dll",
"designer.exe",
"linguist.exe",
"lrelease.exe",
"lupdate.exe",
"lconvert.exe",
"qtdiag.exe"
]
# Choose which EGL library variants to copy.
qt_artifacts_egl = [
"libEGL{}.dll",
"libGLESv2{}.dll"
]
if self.qtinfo.build_type != 'debug_and_release':
egl_suffix = '*'
elif self.debug:
egl_suffix = 'd'
else:
egl_suffix = ''
qt_artifacts_egl = [a.format(egl_suffix) for a in qt_artifacts_egl]
artifacts = []
if copy_qt_permanent_artifacts:
artifacts += qt_artifacts_permanent
artifacts += qt_artifacts_egl
if copy_msvc_redist:
# The target path has to be qt_bin_dir at the moment,
# because the extracted archive also contains the opengl32sw
# and the d3dcompiler dlls, which are copied not by this
# function, but by the copydir below.
copy_msvc_redist_files(vars, "{qt_bin_dir}".format(**vars))
if artifacts:
copydir("{qt_bin_dir}",
"{st_build_dir}/{st_package_name}",
filter=artifacts, recursive=False, vars=vars)
# /bin/*.dll and Qt *.pdbs -> /{st_package_name} part two
# File filter to copy only debug or only release files.
if constrain_modules:
qt_dll_patterns = ["Qt5" + x + "{}.dll" for x in constrain_modules]
if copy_pdbs:
qt_dll_patterns += ["Qt5" + x + "{}.pdb" for x in constrain_modules]
else:
qt_dll_patterns = ["Qt5*{}.dll", "lib*{}.dll"]
if copy_pdbs:
qt_dll_patterns += ["Qt5*{}.pdb", "lib*{}.pdb"]
def qt_build_config_filter(patterns, file_name, file_full_path):
release = [a.format('') for a in patterns]
debug = [a.format('d') for a in patterns]
# If qt is not a debug_and_release build, that means there
# is only one set of shared libraries, so we can just copy
# them.
if self.qtinfo.build_type != 'debug_and_release':
if filter_match(file_name, release):
return True
return False
# In debug_and_release case, choosing which files to copy
# is more difficult. We want to copy only the files that
# match the PySide2 build type. So if PySide2 is built in
# debug mode, we want to copy only Qt debug libraries
# (ending with "d.dll"). Or vice versa. The problem is that
# some libraries have "d" as the last character of the
# actual library name (for example Qt5Gamepad.dll and
# Qt5Gamepadd.dll). So we can't just match a pattern ending
# in "d". Instead we check if there exists a file with the
# same name plus an additional "d" at the end, and using
# that information we can judge if the currently processed
# file is a debug or release file.
# e.g. ["Qt5Cored", ".dll"]
file_split = os.path.splitext(file_name)
file_base_name = file_split[0]
file_ext = file_split[1]
# e.g. "/home/work/qt/qtbase/bin"
file_path_dir_name = os.path.dirname(file_full_path)
# e.g. "Qt5Coredd"
maybe_debug_name = "{}d".format(file_base_name)
if self.debug:
filter = debug
def predicate(path):
return not os.path.exists(path)
else:
filter = release
def predicate(path):
return os.path.exists(path)
# e.g. "/home/work/qt/qtbase/bin/Qt5Coredd.dll"
other_config_path = os.path.join(file_path_dir_name, maybe_debug_name + file_ext)
if (filter_match(file_name, filter) and predicate(other_config_path)):
return True
return False
qt_dll_filter = functools.partial(qt_build_config_filter,
qt_dll_patterns)
copydir("{qt_bin_dir}",
"{st_build_dir}/{st_package_name}",
file_filter_function=qt_dll_filter,
recursive=False, vars=vars)
if copy_plugins:
# /plugins/* -> /{st_package_name}/plugins
plugin_dll_patterns = ["*{}.dll"]
pdb_pattern = "*{}.pdb"
if copy_pdbs:
plugin_dll_patterns += [pdb_pattern]
plugin_dll_filter = functools.partial(qt_build_config_filter, plugin_dll_patterns)
copydir("{qt_plugins_dir}", "{st_build_dir}/{st_package_name}/plugins",
file_filter_function=plugin_dll_filter,
vars=vars)
if copy_translations:
# /translations/* -> /{st_package_name}/translations
copydir("{qt_translations_dir}",
"{st_build_dir}/{st_package_name}/translations",
filter=["*.qm", "*.pak"],
force=False,
vars=vars)
if copy_qml:
# /qml/* -> /{st_package_name}/qml
qml_dll_patterns = ["*{}.dll"]
qml_ignore_patterns = qml_dll_patterns + [pdb_pattern]
qml_ignore = [a.format('') for a in qml_ignore_patterns]
# Copy all files that are not dlls and pdbs (.qml, qmldir).
copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml",
ignore=qml_ignore,
force=False,
recursive=True,
vars=vars)
if copy_pdbs:
qml_dll_patterns += [pdb_pattern]
qml_dll_filter = functools.partial(qt_build_config_filter, qml_dll_patterns)
# Copy all dlls (and possibly pdbs).
copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml",
file_filter_function=qml_dll_filter,
force=False,
recursive=True,
vars=vars)
if self.is_webengine_built(built_modules):
copydir("{qt_prefix_dir}/resources",
"{st_build_dir}/{st_package_name}/resources",
filter=None,
recursive=False,
vars=vars)
filter = 'QtWebEngineProcess{}.exe'.format(
'd' if self.debug else '')
copydir("{qt_bin_dir}",
"{st_build_dir}/{st_package_name}",
filter=[filter],
recursive=False, vars=vars)
if copy_qt_conf:
# Copy the qt.conf file to prefix dir.
copyfile("{build_dir}/pyside2/{st_package_name}/qt.conf",
"{st_build_dir}/{st_package_name}",
vars=vars)
if copy_clang:
self.prepare_standalone_clang(is_win=True)
build_scripts/qp5_tool.py 0000664 0000000 0000000 00000034025 13766170131 0016051 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2019 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
from argparse import ArgumentParser, RawTextHelpFormatter
import datetime
from enum import Enum
import os
import re
import subprocess
import sys
import time
import warnings
DESC = """
Utility script for working with Qt for Python.
Feel free to extend!
Typical Usage:
Update and build a repository: python qp5_tool -p -b
qp5_tool.py uses a configuration file "%CONFIGFILE%"
in the format key=value.
It is possible to use repository-specific values by adding a key postfixed by
a dash and the repository folder base name, eg:
Modules-pyside-setup512=Core,Gui,Widgets,Network,Test
Configuration keys:
Acceleration Incredibuild or unset
BuildArguments Arguments to setup.py
Generator Generator to be used for CMake. Currently, only Ninja is
supported.
Jobs Number of jobs to be run simultaneously
Modules Comma separated list of modules to be built
(for --module-subset=)
Python Python executable (Use python_d for debug builds on Windows)
Arbitrary keys can be defined and referenced by $(name):
MinimalModules=Core,Gui,Widgets,Network,Test
Modules=$(MinimalModules),Multimedia
Modules-pyside-setup-minimal=$(MinimalModules)
"""
class Acceleration(Enum):
NONE = 0
INCREDIBUILD = 1
class BuildMode(Enum):
NONE = 0
BUILD = 1
RECONFIGURE = 2
MAKE = 3
DEFAULT_BUILD_ARGS = ['--build-tests', '--skip-docs', '--quiet']
IS_WINDOWS = sys.platform == 'win32'
INCREDIBUILD_CONSOLE = 'BuildConsole' if IS_WINDOWS else '/opt/incredibuild/bin/ib_console'
# Config file keys
ACCELERATION_KEY = 'Acceleration'
BUILDARGUMENTS_KEY = 'BuildArguments'
GENERATOR_KEY = 'Generator'
JOBS_KEY = 'Jobs'
MODULES_KEY = 'Modules'
PYTHON_KEY = 'Python'
DEFAULT_MODULES = "Core,Gui,Widgets,Network,Test,Qml,Quick,Multimedia,MultimediaWidgets"
DEFAULT_CONFIG_FILE = "Modules={}\n".format(DEFAULT_MODULES)
build_mode = BuildMode.NONE
opt_dry_run = False
def which(needle):
"""Perform a path search"""
needles = [needle]
if IS_WINDOWS:
for ext in ("exe", "bat", "cmd"):
needles.append("{}.{}".format(needle, ext))
for path in os.environ.get("PATH", "").split(os.pathsep):
for n in needles:
binary = os.path.join(path, n)
if os.path.isfile(binary):
return binary
return None
def command_log_string(args, dir):
result = '[{}]'.format(os.path.basename(dir))
for arg in args:
result += ' "{}"'.format(arg) if ' ' in arg else ' {}'.format(arg)
return result
def execute(args):
"""Execute a command and print to log"""
log_string = command_log_string(args, os.getcwd())
print(log_string)
if opt_dry_run:
return
exit_code = subprocess.call(args)
if exit_code != 0:
raise RuntimeError('FAIL({}): {}'.format(exit_code, log_string))
def run_process_output(args):
"""Run a process and return its output. Also run in dry_run mode"""
std_out = subprocess.Popen(args, universal_newlines=1,
stdout=subprocess.PIPE).stdout
result = [line.rstrip() for line in std_out.readlines()]
std_out.close()
return result
def run_git(args):
"""Run git in the current directory and its submodules"""
args.insert(0, git) # run in repo
execute(args) # run for submodules
module_args = [git, "submodule", "foreach"]
module_args.extend(args)
execute(module_args)
def expand_reference(cache_dict, value):
"""Expand references to other keys in config files $(name) by value."""
pattern = re.compile(r"\$\([^)]+\)")
while True:
match = pattern.match(value)
if not match:
break
key = match.group(0)[2:-1]
value = value[:match.start(0)] + cache_dict[key] + value[match.end(0):]
return value
def editor():
editor = os.getenv('EDITOR')
if not editor:
return 'notepad' if IS_WINDOWS else 'vi'
editor = editor.strip()
if IS_WINDOWS:
# Windows: git requires quotes in the variable
if editor.startswith('"') and editor.endswith('"'):
editor = editor[1:-1]
editor = editor.replace('/', '\\')
return editor
def edit_config_file():
exit_code = -1
try:
exit_code = subprocess.call([editor(), config_file])
except Exception as e:
reason = str(e)
print('Unable to launch: {}: {}'.format(editor(), reason))
return exit_code
"""
Config file handling, cache and read function
"""
config_dict = {}
def read_config_file(file_name):
"""Read the config file into config_dict, expanding continuation lines"""
global config_dict
keyPattern = re.compile(r'^\s*([A-Za-z0-9\_\-]+)\s*=\s*(.*)$')
with open(file_name) as f:
while True:
line = f.readline()
if not line:
break
line = line.rstrip()
match = keyPattern.match(line)
if match:
key = match.group(1)
value = match.group(2)
while value.endswith('\\'):
value = value.rstrip('\\')
value += f.readline().rstrip()
config_dict[key] = expand_reference(config_dict, value)
def read_config(key):
"""
Read a value from the '$HOME/.qp5_tool' configuration file. When given
a key 'key' for the repository directory '/foo/qt-5', check for the
repo-specific value 'key-qt5' and then for the general 'key'.
"""
if not config_dict:
read_config_file(config_file)
repo_value = config_dict.get(key + '-' + base_dir)
return repo_value if repo_value else config_dict.get(key)
def read_bool_config(key):
value = read_config(key)
return value and value in ['1', 'true', 'True']
def read_int_config(key, default=-1):
value = read_config(key)
return int(value) if value else default
def read_acceleration_config():
value = read_config(ACCELERATION_KEY)
if value:
value = value.lower()
if value == 'incredibuild':
return Acceleration.INCREDIBUILD
return Acceleration.NONE
def read_config_build_arguments():
value = read_config(BUILDARGUMENTS_KEY)
if value:
return re.split(r'\s+', value)
return DEFAULT_BUILD_ARGS
def read_config_modules_argument():
value = read_config(MODULES_KEY)
if value and value != '' and value != 'all':
return '--module-subset=' + value
return None
def read_config_python_binary():
binary = read_config(PYTHON_KEY)
if binary:
return binary
# Use 'python3' unless virtualenv is set
use_py3 = (not os.environ.get('VIRTUAL_ENV') and which('python3'))
return 'python3' if use_py3 else 'python'
def get_config_file(base_name):
home = os.getenv('HOME')
if IS_WINDOWS:
# Set a HOME variable on Windows such that scp. etc.
# feel at home (locating .ssh).
if not home:
home = os.getenv('HOMEDRIVE') + os.getenv('HOMEPATH')
os.environ['HOME'] = home
user = os.getenv('USERNAME')
config_file = os.path.join(os.getenv('APPDATA'), base_name)
else:
user = os.getenv('USER')
config_dir = os.path.join(home, '.config')
if os.path.exists(config_dir):
config_file = os.path.join(config_dir, base_name)
else:
config_file = os.path.join(home, '.' + base_name)
return config_file
def build(target):
"""Run configure and build steps"""
start_time = time.time()
arguments = []
acceleration = read_acceleration_config()
if not IS_WINDOWS and acceleration == Acceleration.INCREDIBUILD:
arguments.append(INCREDIBUILD_CONSOLE)
arguments.append('--avoid') # caching, v0.96.74
arguments.extend([read_config_python_binary(), 'setup.py', target])
arguments.extend(read_config_build_arguments())
generator = read_config(GENERATOR_KEY)
if generator == 'Ninja':
arguments.extend(['--make-spec', 'ninja'])
jobs = read_int_config(JOBS_KEY)
if jobs > 1:
arguments.extend(['-j', str(jobs)])
if build_mode != BuildMode.BUILD:
arguments.extend(['--reuse-build', '--ignore-git'])
if build_mode != BuildMode.RECONFIGURE:
arguments.append('--skip-cmake')
modules = read_config_modules_argument()
if modules:
arguments.append(modules)
if IS_WINDOWS and acceleration == Acceleration.INCREDIBUILD:
arg_string = ' '.join(arguments)
arguments = [INCREDIBUILD_CONSOLE, '/command={}'.format(arg_string)]
execute(arguments)
elapsed_time = int(time.time() - start_time)
print('--- Done({}s) ---'.format(elapsed_time))
def run_tests():
"""Run tests redirected into a log file with a time stamp"""
logfile_name = datetime.datetime.today().strftime("test_%Y%m%d_%H%M.txt")
binary = sys.executable
command = '"{}" testrunner.py test > {}'.format(binary, logfile_name)
print(command_log_string([command], os.getcwd()))
start_time = time.time()
result = 0 if opt_dry_run else os.system(command)
elapsed_time = int(time.time() - start_time)
print('--- Done({}s) ---'.format(elapsed_time))
return result
def create_argument_parser(desc):
parser = ArgumentParser(description=desc, formatter_class=RawTextHelpFormatter)
parser.add_argument('--dry-run', '-d', action='store_true',
help='Dry run, print commands')
parser.add_argument('--edit', '-e', action='store_true',
help='Edit config file')
parser.add_argument('--reset', '-r', action='store_true',
help='Git reset hard to upstream state')
parser.add_argument('--clean', '-c', action='store_true',
help='Git clean')
parser.add_argument('--pull', '-p', action='store_true',
help='Git pull')
parser.add_argument('--build', '-b', action='store_true',
help='Build (configure + build)')
parser.add_argument('--make', '-m', action='store_true', help='Make')
parser.add_argument('--no-install', '-n', action='store_true',
help='Run --build only, do not install')
parser.add_argument('--Make', '-M', action='store_true',
help='cmake + Make (continue broken build)')
parser.add_argument('--test', '-t', action='store_true',
help='Run tests')
parser.add_argument('--version', '-v', action='version', version='%(prog)s 1.0')
return parser
if __name__ == '__main__':
git = None
base_dir = None
config_file = None
user = None
config_file = get_config_file('qp5_tool.conf')
argument_parser = create_argument_parser(DESC.replace('%CONFIGFILE%', config_file))
options = argument_parser.parse_args()
opt_dry_run = options.dry_run
if options.edit:
sys.exit(edit_config_file())
if options.build:
build_mode = BuildMode.BUILD
elif options.make:
build_mode = BuildMode.MAKE
elif options.Make:
build_mode = BuildMode.RECONFIGURE
if build_mode == BuildMode.NONE and not (options.clean or options.reset
or options.pull or options.test):
argument_parser.print_help()
sys.exit(0)
git = 'git'
if which(git) is None:
warnings.warn('Unable to find git', RuntimeWarning)
sys.exit(-1)
if not os.path.exists(config_file):
print('Create initial config file ', config_file, " ..")
with open(config_file, 'w') as f:
f.write(DEFAULT_CONFIG_FILE.format(' '.join(DEFAULT_BUILD_ARGS)))
while not os.path.exists('.gitmodules'):
cwd = os.getcwd()
if cwd == '/' or (IS_WINDOWS and len(cwd) < 4):
warnings.warn('Unable to find git root', RuntimeWarning)
sys.exit(-1)
os.chdir(os.path.dirname(cwd))
base_dir = os.path.basename(os.getcwd())
if options.clean:
run_git(['clean', '-dxf'])
if options.reset:
run_git(['reset', '--hard', '@{upstream}'])
if options.pull:
run_git(['pull', '--rebase'])
if build_mode != BuildMode.NONE:
target = 'build' if options.no_install else 'install'
build(target)
if options.test:
sys.exit(run_tests())
sys.exit(0)
build_scripts/qtinfo.py 0000664 0000000 0000000 00000023322 13766170131 0015605 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import os
import sys
import re
import subprocess
def _effective_qmake_command(qmake, qt_version):
"""Check whether qmake path is a link to qtchooser and append the
desired Qt version in that case"""
result = [qmake]
# Looking whether qmake path is a link to qtchooser and whether the link
# exists
if os.path.islink(qmake) and os.path.lexists(qmake):
if not qt_version:
print('--qt must be specified when using qtchooser.')
sys.exit(-1)
# Set -qt=X here.
if "qtchooser" in os.readlink(qmake):
result.append("-qt={}".format(qt_version))
return result
class QtInfo(object):
class __QtInfo: # Python singleton
def __init__(self):
self._qmake_command = None
# Dict to cache qmake values.
self._query_dict = {}
# Dict to cache mkspecs variables.
self._mkspecs_dict = {}
def setup(self, qmake, qt_version):
self._qmake_command = _effective_qmake_command(qmake, qt_version)
def get_qmake_command(self):
qmake_command_string = self._qmake_command[0]
for entry in self._qmake_command[1:]:
qmake_command_string += " {}".format(entry)
return qmake_command_string
def get_version(self):
return self.get_property("QT_VERSION")
def get_bins_path(self):
return self.get_property("QT_INSTALL_BINS")
def get_libs_path(self):
return self.get_property("QT_INSTALL_LIBS")
def get_libs_execs_path(self):
return self.get_property("QT_INSTALL_LIBEXECS")
def get_plugins_path(self):
return self.get_property("QT_INSTALL_PLUGINS")
def get_prefix_path(self):
return self.get_property("QT_INSTALL_PREFIX")
def get_imports_path(self):
return self.get_property("QT_INSTALL_IMPORTS")
def get_translations_path(self):
return self.get_property("QT_INSTALL_TRANSLATIONS")
def get_headers_path(self):
return self.get_property("QT_INSTALL_HEADERS")
def get_docs_path(self):
return self.get_property("QT_INSTALL_DOCS")
def get_qml_path(self):
return self.get_property("QT_INSTALL_QML")
def get_macos_deployment_target(self):
""" Return value is a macOS version or None. """
return self.get_property("QMAKE_MACOSX_DEPLOYMENT_TARGET")
def get_build_type(self):
"""
Return value is either debug, release, debug_release, or None.
"""
return self.get_property("BUILD_TYPE")
def get_src_dir(self):
""" Return path to Qt src dir or None.. """
return self.get_property("QT_INSTALL_PREFIX/src")
def get_property(self, prop_name):
if not self._query_dict:
self._get_query_properties()
self._get_other_properties()
if prop_name not in self._query_dict:
return None
return self._query_dict[prop_name]
def get_mkspecs_variables(self):
return self._mkspecs_dict
def _get_qmake_output(self, args_list=[]):
assert(self._qmake_command)
cmd = self._qmake_command + args_list
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False)
output = proc.communicate()[0]
proc.wait()
if proc.returncode != 0:
return ""
if sys.version_info >= (3,):
output = str(output, 'ascii').strip()
else:
output = output.strip()
return output
def _parse_query_properties(self, process_output):
props = {}
if not process_output:
return props
lines = [s.strip() for s in process_output.splitlines()]
for line in lines:
if line and ':' in line:
key, value = line.split(':', 1)
props[key] = value
return props
def _get_query_properties(self):
output = self._get_qmake_output(['-query'])
self._query_dict = self._parse_query_properties(output)
def _parse_qt_build_type(self):
key = 'QT_CONFIG'
if key not in self._mkspecs_dict:
return None
qt_config = self._mkspecs_dict[key]
if 'debug_and_release' in qt_config:
return 'debug_and_release'
split = qt_config.split(' ')
if 'release' in split and 'debug' in split:
return 'debug_and_release'
if 'release' in split:
return 'release'
if 'debug' in split:
return 'debug'
return None
def _get_other_properties(self):
# Get the src property separately, because it is not returned by
# qmake unless explicitly specified.
key = 'QT_INSTALL_PREFIX/src'
result = self._get_qmake_output(['-query', key])
self._query_dict[key] = result
# Get mkspecs variables and cache them.
self._get_qmake_mkspecs_variables()
# Get macOS minimum deployment target.
key = 'QMAKE_MACOSX_DEPLOYMENT_TARGET'
if key in self._mkspecs_dict:
self._query_dict[key] = self._mkspecs_dict[key]
# Figure out how Qt was built:
# debug mode, release mode, or both.
build_type = self._parse_qt_build_type()
if build_type:
self._query_dict['BUILD_TYPE'] = build_type
def _get_qmake_mkspecs_variables(self):
# Create empty temporary qmake project file.
temp_file_name = 'qmake_fake_empty_project.txt'
open(temp_file_name, 'a').close()
# Query qmake for all of its mkspecs variables.
qmake_output = self._get_qmake_output(['-E', temp_file_name])
lines = [s.strip() for s in qmake_output.splitlines()]
pattern = re.compile(r"^(.+?)=(.+?)$")
for line in lines:
found = pattern.search(line)
if found:
key = found.group(1).strip()
value = found.group(2).strip()
self._mkspecs_dict[key] = value
# We need to clean up after qmake, which always creates a
# .qmake.stash file after a -E invocation.
qmake_stash_file = os.path.join(os.getcwd(), ".qmake.stash")
if os.path.exists(qmake_stash_file):
os.remove(qmake_stash_file)
# Also clean up the temporary empty project file.
if os.path.exists(temp_file_name):
os.remove(temp_file_name)
version = property(get_version)
bins_dir = property(get_bins_path)
libs_dir = property(get_libs_path)
lib_execs_dir = property(get_libs_execs_path)
plugins_dir = property(get_plugins_path)
prefix_dir = property(get_prefix_path)
qmake_command = property(get_qmake_command)
imports_dir = property(get_imports_path)
translations_dir = property(get_translations_path)
headers_dir = property(get_headers_path)
docs_dir = property(get_docs_path)
qml_dir = property(get_qml_path)
macos_min_deployment_target = property(get_macos_deployment_target)
build_type = property(get_build_type)
src_dir = property(get_src_dir)
_instance = None # singleton helpers
def __new__(cls): # __new__ always a classmethod
if not QtInfo._instance:
QtInfo._instance = QtInfo.__QtInfo()
return QtInfo._instance
def __getattr__(self, name):
return getattr(self._instance, name)
def __setattr__(self, name):
return setattr(self._instance, name)
build_scripts/setup_runner.py 0000664 0000000 0000000 00000017050 13766170131 0017037 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import sys
import os
import textwrap
from setuptools import setup # Import setuptools before distutils
import distutils.log as log
from build_scripts.config import config
from build_scripts.main import get_package_version, get_setuptools_extension_modules
from build_scripts.main import cmd_class_dict
from build_scripts.options import ADDITIONAL_OPTIONS, OPTION
from build_scripts.utils import run_process
class SetupRunner(object):
def __init__(self, orig_argv):
self.invocations_list = []
# Keep the original args around in case we ever need to pass
# modified arguments to the sub invocations.
self.orig_argv = orig_argv
self.sub_argv = list(orig_argv)
self.setup_script_dir = os.getcwd()
@staticmethod
def cmd_line_argument_is_in_args(argument, args):
""" Check if command line argument was passed in args. """
return any(arg for arg in list(args) if "--" + argument in arg)
@staticmethod
def remove_cmd_line_argument_in_args(argument, args):
""" Remove command line argument from args. """
return [arg for arg in list(args) if "--" + argument not in arg]
@staticmethod
def construct_cmd_line_argument(name, value=None):
""" Constructs a command line argument given name and value. """
if not value:
return "--{}".format(name)
return "--{}={}".format(name, value)
@staticmethod
def construct_internal_build_type_cmd_line_argument(internal_build_type):
return SetupRunner.construct_cmd_line_argument("internal-build-type", internal_build_type)
def add_setup_internal_invocation(self, build_type, reuse_build=False):
""" Enqueues a script sub-invocation to be executed later. """
internal_build_type_arg = self.construct_internal_build_type_cmd_line_argument(build_type)
setup_cmd = [sys.executable] + self.sub_argv + [internal_build_type_arg]
# Add --reuse-build option if requested and not already present.
if reuse_build and not self.cmd_line_argument_is_in_args("reuse-build", self.sub_argv):
setup_cmd.append(self.construct_cmd_line_argument("reuse-build"))
self.invocations_list.append(setup_cmd)
def run_setup(self):
"""
Decide what kind of build is requested and then execute it.
In the top-level invocation case, the script
will spawn setup.py again (possibly multiple times).
In the internal invocation case, the script
will run setuptools.setup().
"""
# Prepare initial config.
config.init_config(build_type=OPTION["BUILD_TYPE"],
internal_build_type=OPTION["INTERNAL_BUILD_TYPE"],
cmd_class_dict=cmd_class_dict,
package_version=get_package_version(),
ext_modules=get_setuptools_extension_modules(),
setup_script_dir=self.setup_script_dir,
quiet=OPTION["QUIET"])
# This is an internal invocation of setup.py, so start actual
# build.
if config.is_internal_invocation():
if config.internal_build_type not in config.get_allowed_internal_build_values():
raise RuntimeError("Invalid '{}' option given to --internal-build-type. "
.format(config.internal_build_type))
self.run_setuptools_setup()
return
# This is a top-level invocation of setup.py, so figure out what
# modules we will build and depending on that, call setup.py
# multiple times with different arguments.
if config.build_type not in config.get_allowed_top_level_build_values():
raise RuntimeError("Invalid '{}' option given to --build-type. "
.format(config.build_type))
# Build everything: shiboken2, shiboken2-generator and PySide2.
help_requested = '--help' in self.sub_argv or '-h' in self.sub_argv
if help_requested:
self.add_setup_internal_invocation(config.pyside_option_name)
elif config.is_top_level_build_all():
self.add_setup_internal_invocation(config.shiboken_module_option_name)
# Reuse the shiboken build for the generator package instead
# of rebuilding it again.
self.add_setup_internal_invocation(config.shiboken_generator_option_name,
reuse_build=True)
self.add_setup_internal_invocation(config.pyside_option_name)
elif config.is_top_level_build_shiboken_module():
self.add_setup_internal_invocation(config.shiboken_module_option_name)
elif config.is_top_level_build_shiboken_generator():
self.add_setup_internal_invocation(config.shiboken_generator_option_name)
elif config.is_top_level_build_pyside():
self.add_setup_internal_invocation(config.pyside_option_name)
for cmd in self.invocations_list:
cmd_as_string = " ".join(cmd)
log.info("\nRunning setup: {}\n".format(cmd_as_string))
exit_code = run_process(cmd)
if exit_code != 0:
msg = textwrap.dedent("""
setup.py invocation failed with exit code: {}.\n\n
setup.py invocation was: {}
""").format(exit_code, cmd_as_string)
raise RuntimeError(msg)
if help_requested:
print(ADDITIONAL_OPTIONS)
@staticmethod
def run_setuptools_setup():
"""
Runs setuptools.setup() once in a single setup.py
sub-invocation.
"""
kwargs = config.setup_kwargs
setup(**kwargs)
build_scripts/utils.py 0000664 0000000 0000000 00000121103 13766170131 0015441 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
import sys
import os
import re
import stat
import errno
import shutil
import subprocess
import fnmatch
import itertools
import glob
# There is no urllib.request in Python2
try:
import urllib.request as urllib
except ImportError:
import urllib
import distutils.log as log
from distutils.errors import DistutilsSetupError
try:
WindowsError
except NameError:
WindowsError = None
def filter_match(name, patterns):
for pattern in patterns:
if pattern is None:
continue
if fnmatch.fnmatch(name, pattern):
return True
return False
def update_env_path(newpaths):
paths = os.environ['PATH'].lower().split(os.pathsep)
for path in newpaths:
if not path.lower() in paths:
log.info("Inserting path '{}' to environment".format(path))
paths.insert(0, path)
os.environ['PATH'] = "{}{}{}".format(path, os.pathsep, os.environ['PATH'])
def winsdk_setenv(platform_arch, build_type):
from distutils.msvc9compiler import VERSION as MSVC_VERSION
from distutils.msvc9compiler import Reg
from distutils.msvc9compiler import HKEYS
from distutils.msvc9compiler import WINSDK_BASE
sdk_version_map = {
"v6.0a": 9.0,
"v6.1": 9.0,
"v7.0": 9.0,
"v7.0a": 10.0,
"v7.1": 10.0
}
log.info("Searching Windows SDK with MSVC compiler version {}".format(MSVC_VERSION))
setenv_paths = []
for base in HKEYS:
sdk_versions = Reg.read_keys(base, WINSDK_BASE)
if sdk_versions:
for sdk_version in sdk_versions:
installationfolder = Reg.get_value("{}\\{}".format(WINSDK_BASE, sdk_version),
"installationfolder")
# productversion = Reg.get_value("{}\\{}".format(WINSDK_BASE, sdk_version),
# "productversion")
setenv_path = os.path.join(installationfolder, os.path.join('bin', 'SetEnv.cmd'))
if not os.path.exists(setenv_path):
continue
if sdk_version not in sdk_version_map:
continue
if sdk_version_map[sdk_version] != MSVC_VERSION:
continue
setenv_paths.append(setenv_path)
if len(setenv_paths) == 0:
raise DistutilsSetupError("Failed to find the Windows SDK with MSVC compiler "
"version {}".format(MSVC_VERSION))
for setenv_path in setenv_paths:
log.info("Found {}".format(setenv_path))
# Get SDK env (use latest SDK version installed on system)
setenv_path = setenv_paths[-1]
log.info("Using {} ".format(setenv_path))
build_arch = "/x86" if platform_arch.startswith("32") else "/x64"
build_type = "/Debug" if build_type.lower() == "debug" else "/Release"
setenv_cmd = [setenv_path, build_arch, build_type]
setenv_env = get_environment_from_batch_command(setenv_cmd)
setenv_env_paths = os.pathsep.join([setenv_env[k] for k in setenv_env if k.upper() == 'PATH']).split(os.pathsep)
setenv_env_without_paths = dict([(k, setenv_env[k]) for k in setenv_env if k.upper() != 'PATH'])
# Extend os.environ with SDK env
log.info("Initializing Windows SDK env...")
update_env_path(setenv_env_paths)
for k in sorted(setenv_env_without_paths):
v = setenv_env_without_paths[k]
log.info("Inserting '{} = {}' to environment".format(k, v))
os.environ[k] = v
log.info("Done initializing Windows SDK env")
def find_vcdir(version):
"""
This is the customized version of
distutils.msvc9compiler.find_vcvarsall method
"""
from distutils.msvc9compiler import VS_BASE
from distutils.msvc9compiler import Reg
vsbase = VS_BASE % version
try:
productdir = Reg.get_value(r"{}\Setup\VC".format(vsbase), "productdir")
except KeyError:
productdir = None
# trying Express edition
if productdir is None:
try:
from distutils.msvc9compiler import VSEXPRESS_BASE
except ImportError:
pass
else:
vsbase = VSEXPRESS_BASE % version
try:
productdir = Reg.get_value(r"{}\Setup\VC".format(vsbase), "productdir")
except KeyError:
productdir = None
log.debug("Unable to find productdir in registry")
if not productdir or not os.path.isdir(productdir):
toolskey = "VS{:0.0f}0COMNTOOLS".format(version)
toolsdir = os.environ.get(toolskey, None)
if toolsdir and os.path.isdir(toolsdir):
productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
productdir = os.path.abspath(productdir)
if not os.path.isdir(productdir):
log.debug("{} is not a valid directory".format(productdir))
return None
else:
log.debug("Env var {} is not set or invalid".format(toolskey))
if not productdir:
log.debug("No productdir found")
return None
return productdir
def init_msvc_env(platform_arch, build_type):
from distutils.msvc9compiler import VERSION as MSVC_VERSION
log.info("Searching MSVC compiler version {}".format(MSVC_VERSION))
vcdir_path = find_vcdir(MSVC_VERSION)
if not vcdir_path:
raise DistutilsSetupError("Failed to find the MSVC compiler version {} on your "
"system.".format(MSVC_VERSION))
else:
log.info("Found {}".format(vcdir_path))
log.info("Searching MSVC compiler {} environment init script".format(MSVC_VERSION))
if platform_arch.startswith("32"):
vcvars_path = os.path.join(vcdir_path, "bin", "vcvars32.bat")
else:
vcvars_path = os.path.join(vcdir_path, "bin", "vcvars64.bat")
if not os.path.exists(vcvars_path):
vcvars_path = os.path.join(vcdir_path, "bin", "amd64", "vcvars64.bat")
if not os.path.exists(vcvars_path):
vcvars_path = os.path.join(vcdir_path, "bin", "amd64", "vcvarsamd64.bat")
if not os.path.exists(vcvars_path):
# MSVC init script not found, try to find and init Windows SDK env
log.error("Failed to find the MSVC compiler environment init script "
"(vcvars.bat) on your system.")
winsdk_setenv(platform_arch, build_type)
return
else:
log.info("Found {}".format(vcvars_path))
# Get MSVC env
log.info("Using MSVC {} in {}".format(MSVC_VERSION, vcvars_path))
msvc_arch = "x86" if platform_arch.startswith("32") else "amd64"
log.info("Getting MSVC env for {} architecture".format(msvc_arch))
vcvars_cmd = [vcvars_path, msvc_arch]
msvc_env = get_environment_from_batch_command(vcvars_cmd)
msvc_env_paths = os.pathsep.join([msvc_env[k] for k in msvc_env if k.upper() == 'PATH']).split(os.pathsep)
msvc_env_without_paths = dict([(k, msvc_env[k]) for k in msvc_env if k.upper() != 'PATH'])
# Extend os.environ with MSVC env
log.info("Initializing MSVC env...")
update_env_path(msvc_env_paths)
for k in sorted(msvc_env_without_paths):
v = msvc_env_without_paths[k]
log.info("Inserting '{} = {}' to environment".format(k, v))
os.environ[k] = v
log.info("Done initializing MSVC env")
def copyfile(src, dst, force=True, vars=None, force_copy_symlink=False,
make_writable_by_owner=False):
if vars is not None:
src = src.format(**vars)
dst = dst.format(**vars)
if not os.path.exists(src) and not force:
log.info("**Skiping copy file {} to {}. Source does not exists.".format(src, dst))
return
if not os.path.islink(src) or force_copy_symlink:
log.info("Copying file {} to {}.".format(src, dst))
shutil.copy2(src, dst)
if make_writable_by_owner:
make_file_writable_by_owner(dst)
else:
link_target_path = os.path.realpath(src)
if os.path.dirname(link_target_path) == os.path.dirname(src):
link_target = os.path.basename(link_target_path)
link_name = os.path.basename(src)
current_directory = os.getcwd()
try:
target_dir = dst if os.path.isdir(dst) else os.path.dirname(dst)
os.chdir(target_dir)
if os.path.exists(link_name):
os.remove(link_name)
log.info("Symlinking {} -> {} in {}.".format(link_name, link_target, target_dir))
os.symlink(link_target, link_name)
except OSError:
log.error("{} -> {}: Error creating symlink".format(link_name, link_target))
finally:
os.chdir(current_directory)
else:
log.error("{} -> {}: Can only create symlinks within the same "
"directory".format(src, link_target_path))
return dst
def makefile(dst, content=None, vars=None):
if vars is not None:
if content is not None:
content = content.format(**vars)
dst = dst.format(**vars)
log.info("Making file {}.".format(dst))
dstdir = os.path.dirname(dst)
if not os.path.exists(dstdir):
os.makedirs(dstdir)
with open(dst, "wt") as f:
if content is not None:
f.write(content)
def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, vars=None,
dir_filter_function=None, file_filter_function=None, force_copy_symlinks=False):
if vars is not None:
src = src.format(**vars)
dst = dst.format(**vars)
if filter is not None:
for i in range(len(filter)):
filter[i] = filter[i].format(**vars)
if ignore is not None:
for i in range(len(ignore)):
ignore[i] = ignore[i].format(**vars)
if not os.path.exists(src) and not force:
log.info("**Skiping copy tree {} to {}. Source does not exists. "
"filter={}. ignore={}.".format(src, dst, filter, ignore))
return []
log.info("Copying tree {} to {}. filter={}. ignore={}.".format(src, dst, filter, ignore))
names = os.listdir(src)
results = []
errors = []
for name in names:
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if os.path.isdir(srcname):
if (dir_filter_function and not dir_filter_function(name, src, srcname)):
continue
if recursive:
results.extend(copydir(srcname, dstname, filter, ignore, force, recursive,
vars, dir_filter_function, file_filter_function,
force_copy_symlinks))
else:
if ((file_filter_function is not None and not file_filter_function(name, srcname))
or (filter is not None and not filter_match(name, filter))
or (ignore is not None and filter_match(name, ignore))):
continue
if not os.path.exists(dst):
os.makedirs(dst)
results.append(copyfile(srcname, dstname, True, vars, force_copy_symlinks))
# catch the Error from the recursive copytree so that we can
# continue with other files
except shutil.Error as err:
errors.extend(err.args[0])
except EnvironmentError as why:
errors.append((srcname, dstname, str(why)))
try:
if os.path.exists(dst):
shutil.copystat(src, dst)
except OSError as why:
if WindowsError is not None and isinstance(why, WindowsError):
# Copying file access times may fail on Windows
pass
else:
errors.extend((src, dst, str(why)))
if errors:
raise EnvironmentError(errors)
return results
def make_file_writable_by_owner(path):
current_permissions = stat.S_IMODE(os.lstat(path).st_mode)
os.chmod(path, current_permissions | stat.S_IWUSR)
def rmtree(dirname, ignore=False):
def handle_remove_readonly(func, path, exc):
excvalue = exc[1]
if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777
func(path)
else:
raise IOError
shutil.rmtree(dirname, ignore_errors=ignore, onerror=handle_remove_readonly)
def run_process_output(args, initial_env=None):
if initial_env is None:
initial_env = os.environ
std_out = subprocess.Popen(args, env=initial_env, universal_newlines=1,
stdout=subprocess.PIPE).stdout
result = []
for raw_line in std_out.readlines():
line = raw_line if sys.version_info >= (3,) else raw_line.decode('utf-8')
result.append(line.rstrip())
std_out.close()
return result
def run_process(args, initial_env=None):
"""
Run process until completion and return the process exit code.
No output is captured.
"""
command = " ".join([(" " in x and '"{}"'.format(x) or x) for x in args])
log.info("In directory {}:\n\tRunning command: {}".format(os.getcwd(), command))
if initial_env is None:
initial_env = os.environ
kwargs = {}
kwargs['env'] = initial_env
exit_code = subprocess.call(args, **kwargs)
return exit_code
def get_environment_from_batch_command(env_cmd, initial=None):
"""
Take a command (either a single command or list of arguments)
and return the environment created after running that command.
Note that if the command must be a batch file or .cmd file, or the
changes to the environment will not be captured.
If initial is supplied, it is used as the initial environment passed
to the child process.
"""
def validate_pair(ob):
try:
if not (len(ob) == 2):
print("Unexpected result: {}".format(ob))
raise ValueError
except:
return False
return True
def consume(iter):
try:
while True:
next(iter)
except StopIteration:
pass
if not isinstance(env_cmd, (list, tuple)):
env_cmd = [env_cmd]
# construct the command that will alter the environment
env_cmd = subprocess.list2cmdline(env_cmd)
# create a tag so we can tell in the output when the proc is done
tag = 'Done running command'
# construct a cmd.exe command to do accomplish this
cmd = 'cmd.exe /E:ON /V:ON /s /c "{} && echo "{}" && set"'.format(env_cmd, tag)
# launch the process
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
# parse the output sent to stdout
lines = proc.stdout
if sys.version_info[0] > 2:
# make sure the lines are strings
lines = map(lambda s: s.decode(), lines)
# consume whatever output occurs until the tag is reached
consume(itertools.takewhile(lambda l: tag not in l, lines))
# define a way to handle each KEY=VALUE line
# parse key/values into pairs
pairs = map(lambda l: l.rstrip().split('=', 1), lines)
# make sure the pairs are valid
valid_pairs = filter(validate_pair, pairs)
# construct a dictionary of the pairs
result = dict(valid_pairs)
# let the process finish
proc.communicate()
return result
def regenerate_qt_resources(src, pyside_rcc_path, pyside_rcc_options):
names = os.listdir(src)
for name in names:
srcname = os.path.join(src, name)
if os.path.isdir(srcname):
regenerate_qt_resources(srcname, pyside_rcc_path, pyside_rcc_options)
elif srcname.endswith('.qrc'):
# Replace last occurence of '.qrc' in srcname
srcname_split = srcname.rsplit('.qrc', 1)
dstname = '_rc.py'.join(srcname_split)
if os.path.exists(dstname):
log.info('Regenerating {} from {}'.format(dstname, os.path.basename(srcname)))
run_process([pyside_rcc_path] + pyside_rcc_options + [srcname, '-o', dstname])
def back_tick(cmd, ret_err=False):
"""
Run command `cmd`, return stdout, or stdout, stderr,
return_code if `ret_err` is True.
Roughly equivalent to ``check_output`` in Python 2.7
Parameters
----------
cmd : str
command to execute
ret_err : bool, optional
If True, return stderr and return_code in addition to stdout.
If False, just return stdout
Returns
-------
out : str or tuple
If `ret_err` is False, return stripped string containing stdout from
`cmd`.
If `ret_err` is True, return tuple of (stdout, stderr, return_code)
where ``stdout`` is the stripped stdout, and ``stderr`` is the stripped
stderr, and ``return_code`` is the process exit code.
Raises
------
Raises RuntimeError if command returns non-zero exit code when ret_err
isn't set.
"""
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
out, err = proc.communicate()
if not isinstance(out, str):
# python 3
out = out.decode()
err = err.decode()
retcode = proc.returncode
if retcode is None and not ret_err:
proc.terminate()
raise RuntimeError("{} process did not terminate".format(cmd))
if retcode != 0 and not ret_err:
raise RuntimeError("{} process returned code {}\n*** {}".format(
(cmd, retcode, err)))
out = out.strip()
if not ret_err:
return out
return out, err.strip(), retcode
MACOS_OUTNAME_RE = re.compile(r'\(compatibility version [\d.]+, current version [\d.]+\)')
def macos_get_install_names(libpath):
"""
Get macOS library install names from library `libpath` using ``otool``
Parameters
----------
libpath : str
path to library
Returns
-------
install_names : list of str
install names in library `libpath`
"""
out = back_tick("otool -L {}".format(libpath))
libs = [line for line in out.split('\n')][1:]
return [MACOS_OUTNAME_RE.sub('', lib).strip() for lib in libs]
MACOS_RPATH_RE = re.compile(r"path (.+) \(offset \d+\)")
def macos_get_rpaths(libpath):
""" Get rpath load commands from library `libpath` using ``otool``
Parameters
----------
libpath : str
path to library
Returns
-------
rpaths : list of str
rpath values stored in ``libpath``
Notes
-----
See ``man dyld`` for more information on rpaths in libraries
"""
lines = back_tick('otool -l {}'.format(libpath)).split('\n')
ctr = 0
rpaths = []
while ctr < len(lines):
line = lines[ctr].strip()
if line != 'cmd LC_RPATH':
ctr += 1
continue
assert lines[ctr + 1].strip().startswith('cmdsize')
rpath_line = lines[ctr + 2].strip()
match = MACOS_RPATH_RE.match(rpath_line)
if match is None:
raise RuntimeError("Unexpected path line: {}".format(rpath_line))
rpaths.append(match.groups()[0])
ctr += 3
return rpaths
def macos_add_rpath(rpath, library_path):
back_tick("install_name_tool -add_rpath {} {}".format(rpath, library_path))
def macos_fix_rpaths_for_library(library_path, qt_lib_dir):
""" Adds required rpath load commands to given library.
This is a necessary post-installation step, to allow loading PySide
modules without setting DYLD_LIBRARY_PATH or DYLD_FRAMEWORK_PATH.
The CMake rpath commands which are added at build time are used only
for testing (make check), and they are stripped once the equivalent
of make install is executed (except for shiboken, which currently
uses CMAKE_INSTALL_RPATH_USE_LINK_PATH, which might be necessary to
remove in the future).
Parameters
----------
library_path : str
path to library for which to set rpaths.
qt_lib_dir : str
rpath to installed Qt lib directory.
"""
install_names = macos_get_install_names(library_path)
existing_rpath_commands = macos_get_rpaths(library_path)
needs_loader_path = False
for install_name in install_names:
# Absolute path, skip it.
if install_name[0] == '/':
continue
# If there are dynamic library install names that contain
# @rpath tokens, we will provide an rpath load command with the
# value of "@loader_path". This will allow loading dependent
# libraries from within the same directory as 'library_path'.
if install_name[0] == '@':
needs_loader_path = True
break
if needs_loader_path and "@loader_path" not in existing_rpath_commands:
macos_add_rpath("@loader_path", library_path)
# If the library depends on a Qt library, add an rpath load comment
# pointing to the Qt lib directory.
macos_add_qt_rpath(library_path, qt_lib_dir, existing_rpath_commands, install_names)
def macos_add_qt_rpath(library_path, qt_lib_dir, existing_rpath_commands=[],
library_dependencies=[]):
"""
Adds an rpath load command to the Qt lib directory if necessary
Checks if library pointed to by 'library_path' has Qt dependencies,
and adds an rpath load command that points to the Qt lib directory
(qt_lib_dir).
"""
if not existing_rpath_commands:
existing_rpath_commands = macos_get_rpaths(library_path)
# Return early if qt rpath is already present.
if qt_lib_dir in existing_rpath_commands:
return
# Check if any library dependencies are Qt libraries (hacky).
if not library_dependencies:
library_dependencies = macos_get_install_names(library_path)
needs_qt_rpath = False
for library in library_dependencies:
if 'Qt' in library:
needs_qt_rpath = True
break
if needs_qt_rpath:
macos_add_rpath(qt_lib_dir, library_path)
# Find an executable specified by a glob pattern ('foo*') in the OS path
def find_glob_in_path(pattern):
result = []
if sys.platform == 'win32':
pattern += '.exe'
for path in os.environ.get('PATH', '').split(os.pathsep):
for match in glob.glob(os.path.join(path, pattern)):
result.append(match)
return result
# Locate the most recent version of llvm_config in the path.
def find_llvm_config():
version_re = re.compile(r'(\d+)\.(\d+)\.(\d+)')
result = None
last_version_string = '000000'
for llvm_config in find_glob_in_path('llvm-config*'):
try:
output = run_process_output([llvm_config, '--version'])
if output:
match = version_re.match(output[0])
if match:
version_string = "{:02d}{:02d}{:02d}".format(int(match.group(1)),
int(match.group(2)),
int(match.group(3)))
if (version_string > last_version_string):
result = llvm_config
last_version_string = version_string
except OSError:
pass
return result
# Add Clang to path for Windows for the shiboken ApiExtractor tests.
# Revisit once Clang is bundled with Qt.
def detect_clang():
source = 'LLVM_INSTALL_DIR'
clang_dir = os.environ.get(source, None)
if not clang_dir:
source = 'CLANG_INSTALL_DIR'
clang_dir = os.environ.get(source, None)
if not clang_dir:
source = find_llvm_config()
try:
if source is not None:
output = run_process_output([source, '--prefix'])
if output:
clang_dir = output[0]
except OSError:
pass
if clang_dir:
arch = '64' if sys.maxsize > 2 ** 31 - 1 else '32'
clang_dir = clang_dir.replace('_ARCH_', arch)
return (clang_dir, source)
_7z_binary = None
def download_and_extract_7z(fileurl, target):
""" Downloads 7z file from fileurl and extract to target """
info = ""
localfile = None
for i in range(1, 10):
try:
print("Downloading fileUrl {}, attempt #{}".format(fileurl, i))
localfile, info = urllib.urlretrieve(fileurl)
break
except:
pass
if not localfile:
print("Error downloading {} : {}".format(fileurl, info))
raise RuntimeError(' Error downloading {}'.format(fileurl))
try:
global _7z_binary
outputDir = "-o{}".format(target)
if not _7z_binary:
if sys.platform == 'win32':
candidate = 'c:\\Program Files\\7-Zip\\7z.exe'
if os.path.exists(candidate):
_7z_binary = candidate
if not _7z_binary:
_7z_binary = '7z'
print("calling {} x {} {}".format(_7z_binary, localfile, outputDir))
subprocess.call([_7z_binary, "x", "-y", localfile, outputDir])
except:
raise RuntimeError(' Error extracting {}'.format(localfile))
def split_and_strip(sinput):
lines = [s.strip() for s in sinput.splitlines()]
return lines
def ldd_get_dependencies(executable_path):
"""
Returns a dictionary of dependencies that `executable_path`
depends on.
The keys are library names and the values are the library paths.
"""
output = ldd(executable_path)
lines = split_and_strip(output)
pattern = re.compile(r"\s*(.*?)\s+=>\s+(.*?)\s+\(.*\)")
dependencies = {}
for line in lines:
match = pattern.search(line)
if match:
dependencies[match.group(1)] = match.group(2)
return dependencies
def ldd_get_paths_for_dependencies(dependencies_regex, executable_path=None, dependencies=None):
"""
Returns file paths to shared library dependencies that match given
`dependencies_regex` against given `executable_path`.
The function retrieves the list of shared library dependencies using
ld.so for the given `executable_path` in order to search for
libraries that match the `dependencies_regex`, and then returns a
list of absolute paths of the matching libraries.
If no matching library is found in the list of dependencies,
an empty list is returned.
"""
if not dependencies and not executable_path:
return None
if not dependencies:
dependencies = ldd_get_dependencies(executable_path)
pattern = re.compile(dependencies_regex)
paths = []
for key in dependencies:
match = pattern.search(key)
if match:
paths.append(dependencies[key])
return paths
def ldd(executable_path):
"""
Returns ld.so output of shared library dependencies for given
`executable_path`.
This is a partial port of /usr/bin/ldd from bash to Python.
The dependency list is retrieved by setting the
LD_TRACE_LOADED_OBJECTS=1 environment variable, and executing the
given path via the dynamic loader ld.so.
Only works on Linux. The port is required to make this work on
systems that might not have ldd.
This is because ldd (on Ubuntu) is shipped in the libc-bin package
that, which might have a
minuscule percentage of not being installed.
Parameters
----------
executable_path : str
path to executable or shared library.
Returns
-------
output : str
the raw output retrieved from the dynamic linker.
"""
chosen_rtld = None
# List of ld's considered by ldd on Ubuntu (here's hoping it's the
# same on all distros).
rtld_list = ["/lib/ld-linux.so.2", "/lib64/ld-linux-x86-64.so.2", "/libx32/ld-linux-x32.so.2"]
# Choose appropriate runtime dynamic linker.
for rtld in rtld_list:
if os.path.isfile(rtld) and os.access(rtld, os.X_OK):
(_, _, code) = back_tick(rtld, True)
# Code 127 is returned by ld.so when called without any
# arguments (some kind of sanity check I guess).
if code == 127:
(_, _, code) = back_tick("{} --verify {}".format(rtld, executable_path), True)
# Codes 0 and 2 mean given executable_path can be
# understood by ld.so.
if code in [0, 2]:
chosen_rtld = rtld
break
if not chosen_rtld:
raise RuntimeError("Could not find appropriate ld.so to query for dependencies.")
# Query for shared library dependencies.
rtld_env = "LD_TRACE_LOADED_OBJECTS=1"
rtld_cmd = "{} {} {}".format(rtld_env, chosen_rtld, executable_path)
(out, _, return_code) = back_tick(rtld_cmd, True)
if return_code == 0:
return out
else:
raise RuntimeError("ld.so failed to query for dependent shared "
"libraries of {} ".format(executable_path))
def find_files_using_glob(path, pattern):
""" Returns list of files that matched glob `pattern` in `path`. """
final_pattern = os.path.join(path, pattern)
maybe_files = glob.glob(final_pattern)
return maybe_files
def find_qt_core_library_glob(lib_dir):
""" Returns path to the QtCore library found in `lib_dir`. """
maybe_file = find_files_using_glob(lib_dir, "libQt5Core.so.?")
if len(maybe_file) == 1:
return maybe_file[0]
return None
# @TODO: Possibly fix ICU library copying on macOS and Windows.
# This would require to implement the equivalent of the custom written
# ldd for the specified platforms.
# This has less priority because ICU libs are not used in the default
# Qt configuration build.
def copy_icu_libs(patchelf, destination_lib_dir):
"""
Copy ICU libraries that QtCore depends on,
to given `destination_lib_dir`.
"""
qt_core_library_path = find_qt_core_library_glob(destination_lib_dir)
if not qt_core_library_path or not os.path.exists(qt_core_library_path):
raise RuntimeError('QtCore library does not exist at path: {}. '
'Failed to copy ICU libraries.'.format(qt_core_library_path))
dependencies = ldd_get_dependencies(qt_core_library_path)
icu_regex = r"^libicu.+"
icu_compiled_pattern = re.compile(icu_regex)
icu_required = False
for dependency in dependencies:
match = icu_compiled_pattern.search(dependency)
if match:
icu_required = True
break
if icu_required:
paths = ldd_get_paths_for_dependencies(icu_regex, dependencies=dependencies)
if not paths:
raise RuntimeError("Failed to find the necessary ICU libraries required by QtCore.")
log.info('Copying the detected ICU libraries required by QtCore.')
if not os.path.exists(destination_lib_dir):
os.makedirs(destination_lib_dir)
for path in paths:
basename = os.path.basename(path)
destination = os.path.join(destination_lib_dir, basename)
copyfile(path, destination, force_copy_symlink=True)
# Patch the ICU libraries to contain the $ORIGIN rpath
# value, so that only the local package libraries are used.
linux_set_rpaths(patchelf, destination, '$ORIGIN')
# Patch the QtCore library to find the copied over ICU libraries
# (if necessary).
log.info("Checking if QtCore library needs a new rpath to make it work with ICU libs.")
rpaths = linux_get_rpaths(qt_core_library_path)
if not rpaths or not rpaths_has_origin(rpaths):
log.info('Patching QtCore library to contain $ORIGIN rpath.')
rpaths.insert(0, '$ORIGIN')
new_rpaths_string = ":".join(rpaths)
linux_set_rpaths(patchelf, qt_core_library_path, new_rpaths_string)
def linux_run_read_elf(executable_path):
cmd = "readelf -d {}".format(executable_path)
(out, err, code) = back_tick(cmd, True)
if code != 0:
raise RuntimeError("Running `readelf -d {}` failed with error "
"output:\n {}. ".format(executable_path, err))
lines = split_and_strip(out)
return lines
def linux_set_rpaths(patchelf, executable_path, rpath_string):
""" Patches the `executable_path` with a new rpath string. """
cmd = [patchelf, '--set-rpath', rpath_string, executable_path]
if run_process(cmd) != 0:
raise RuntimeError("Error patching rpath in {}".format(executable_path))
def linux_get_dependent_libraries(executable_path):
"""
Returns a list of libraries that executable_path depends on.
"""
lines = linux_run_read_elf(executable_path)
pattern = re.compile(r"^.+?\(NEEDED\).+?\[(.+?)\]$")
library_lines = []
for line in lines:
match = pattern.search(line)
if match:
library_line = match.group(1)
library_lines.append(library_line)
return library_lines
def linux_get_rpaths(executable_path):
"""
Returns a list of run path values embedded in the executable or just
an empty list.
"""
lines = linux_run_read_elf(executable_path)
pattern = re.compile(r"^.+?\(RUNPATH\).+?\[(.+?)\]$")
rpath_line = None
for line in lines:
match = pattern.search(line)
if match:
rpath_line = match.group(1)
break
rpaths = []
if rpath_line:
rpaths = rpath_line.split(':')
return rpaths
def rpaths_has_origin(rpaths):
"""
Return True if the specified list of rpaths has an "$ORIGIN" value
(aka current dir).
"""
if not rpaths:
return False
pattern = re.compile(r"^\$ORIGIN(/)?$")
for rpath in rpaths:
match = pattern.search(rpath)
if match:
return True
return False
def linux_needs_qt_rpath(executable_path):
"""
Returns true if library_path depends on Qt libraries.
"""
dependencies = linux_get_dependent_libraries(executable_path)
# Check if any library dependencies are Qt libraries (hacky).
needs_qt_rpath = False
for dep in dependencies:
if 'Qt' in dep:
needs_qt_rpath = True
break
return needs_qt_rpath
def linux_fix_rpaths_for_library(patchelf, executable_path, qt_rpath, override=False):
"""
Adds or overrides required rpaths in given executable / library.
"""
rpaths = ['$ORIGIN/']
existing_rpaths = []
if not override:
existing_rpaths = linux_get_rpaths(executable_path)
rpaths.extend(existing_rpaths)
if linux_needs_qt_rpath(executable_path) and qt_rpath not in existing_rpaths:
rpaths.append(qt_rpath)
rpaths_string = ':'.join(rpaths)
linux_set_rpaths(patchelf, executable_path, rpaths_string)
def memoize(function):
"""
Decorator to wrap a function with a memoizing callable.
It returns cached values when the wrapped function is called with
the same arguments.
"""
memo = {}
def wrapper(*args):
if args in memo:
return memo[args]
else:
rv = function(*args)
memo[args] = rv
return rv
return wrapper
def get_python_dict(python_script_path):
try:
with open(python_script_path) as f:
python_dict = {}
code = compile(f.read(), python_script_path, 'exec')
exec(code, {}, python_dict)
return python_dict
except IOError as e:
print("get_python_dict: Couldn't get dict from python "
"file: {}.".format(python_script_path))
raise
def install_pip_package_from_url_specifier(env_pip, url, upgrade=True):
args = [env_pip, "install", url]
if upgrade:
args.append("--upgrade")
args.append(url)
run_instruction(args, "Failed to install {}".format(url))
def install_pip_dependencies(env_pip, packages, upgrade=True):
for p in packages:
args = [env_pip, "install"]
if upgrade:
args.append("--upgrade")
args.append(p)
run_instruction(args, "Failed to install {}".format(p))
def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch):
_pExe = "python"
_env = "env{}".format(str(python_ver))
env_python = _env + "/bin/python"
env_pip = _env + "/bin/pip"
if host == "Windows":
print("New virtualenv to build {} in {} host".format(targetArch, hostArch))
_pExe = "python.exe"
# With windows we are creating building 32-bit target in 64-bit host
if hostArch == "X86_64" and targetArch == "X86":
if python_ver.startswith("3"):
var = "PYTHON" + python_ver + "-32_PATH"
print("Try to find python from {} env variable".format(var))
_path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
_pExe = os.path.join(os.getenv("PYTHON3_32_PATH"), "python.exe")
else:
_pExe = os.path.join(os.getenv("PYTHON2_32_PATH"), "python.exe")
else:
if python_ver.startswith("3"):
var = "PYTHON" + python_ver + "-64_PATH"
print("Try to find python from {} env variable".format(var))
_path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
_pExe = os.path.join(os.getenv("PYTHON3_PATH"), "python.exe")
env_python = _env + "\\Scripts\\python.exe"
env_pip = _env + "\\Scripts\\pip.exe"
else:
if python_ver == "3":
_pExe = "python3"
return(_pExe, _env, env_pip, env_python)
def run_instruction(instruction, error, initial_env=None):
if initial_env is None:
initial_env = os.environ
print("Running Coin instruction: {}".format(' '.join(str(e) for e in instruction)))
result = subprocess.call(instruction, env=initial_env)
if result != 0:
print("ERROR : {}".format(error))
exit(result)
def acceptCITestConfiguration(hostOS, hostOSVer, targetArch, compiler):
# Disable unsupported CI configs for now
# NOTE: String must match with QT CI's storagestruct thrift
if (hostOSVer in ["WinRT_10", "WebAssembly", "Ubuntu_18_04", "Android_ANY"]
or hostOSVer.startswith("SLES_")):
print("Disabled {} from Coin configuration".format(hostOSVer))
return False
# With 5.11 CI will create two sets of release binaries,
# one with msvc 2015 and one with msvc 2017
# we shouldn't release the 2015 version.
# BUT, 32 bit build is done only on msvc 2015...
if compiler in ["MSVC2015"] and targetArch in ["X86_64"]:
print("Disabled {} to {} from Coin configuration".format(compiler, targetArch))
return False
return True
def get_ci_qmake_path(ci_install_dir, ci_host_os):
qmake_path = "--qmake={}".format(ci_install_dir)
if ci_host_os == "MacOS":
return qmake_path + "/bin/qmake"
elif ci_host_os == "Windows":
return qmake_path + "\\bin\\qmake.exe"
else:
return qmake_path + "/bin/qmake"
build_scripts/wheel_override.py 0000664 0000000 0000000 00000022241 13766170131 0017307 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
wheel_module_exists = False
import os
import sys
from .options import DistUtilsCommandMixin, OPTION
from distutils import log as logger
from email.generator import Generator
from .wheel_utils import get_package_version, get_qt_version, macos_plat_name
try:
from distutils import log as logger
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
from wheel.bdist_wheel import safer_name as _safer_name
from wheel.bdist_wheel import get_abi_tag, get_platform
from packaging import tags
from wheel import __version__ as wheel_version
wheel_module_exists = True
except Exception as e:
_bdist_wheel, wheel_version = type, '' # dummy to make class statement happy
print('***** Exception while trying to prepare bdist_wheel override class: {}. '
'Skipping wheel overriding.'.format(e))
def get_bdist_wheel_override():
return PysideBuildWheel if wheel_module_exists else None
class PysideBuildWheel(_bdist_wheel, DistUtilsCommandMixin):
user_options = (_bdist_wheel.user_options + DistUtilsCommandMixin.mixin_user_options
if wheel_module_exists else None)
def __init__(self, *args, **kwargs):
self._package_version = None
_bdist_wheel.__init__(self, *args, **kwargs)
DistUtilsCommandMixin.__init__(self)
def finalize_options(self):
DistUtilsCommandMixin.mixin_finalize_options(self)
if sys.platform == 'darwin':
# Override the platform name to contain the correct
# minimum deployment target.
# This is used in the final wheel name.
self.plat_name = macos_plat_name()
# When limited API is requested, notify bdist_wheel to
# create a properly named package.
limited_api_enabled = (OPTION["LIMITED_API"] == 'yes'
and sys.version_info[0] >= 3)
if limited_api_enabled:
self.py_limited_api = "cp35.cp36.cp37.cp38.cp39"
self._package_version = get_package_version()
_bdist_wheel.finalize_options(self)
@property
def wheel_dist_name(self):
# Slightly modified version of wheel's wheel_dist_name
# method, to add the Qt version as well.
# Example:
# PySide2-5.6-5.6.4-cp27-cp27m-macosx_10_10_intel.whl
# The PySide2 version is "5.6".
# The Qt version built against is "5.6.4".
wheel_version = "{}-{}".format(self._package_version, get_qt_version())
components = (_safer_name(self.distribution.get_name()), wheel_version)
if self.build_number:
components += (self.build_number,)
return '-'.join(components)
# Copy of get_tag from bdist_wheel.py, to allow setting a
# multi-python impl tag, by removing an assert. Otherwise we
# would have to rename wheels manually for limited api
# packages. Also we set "none" abi tag on Windows, because
# pip does not yet support "abi3" tag, leading to
# installation failure when tried.
def get_tag(self):
# bdist sets self.plat_name if unset, we should only use it for purepy
# wheels if the user supplied it.
if self.plat_name_supplied:
plat_name = self.plat_name
elif self.root_is_pure:
plat_name = 'any'
else:
# macosx contains system version in platform name so need special handle
if self.plat_name and not self.plat_name.startswith("macosx"):
plat_name = self.plat_name
else:
# on macosx always limit the platform name to comply with any
# c-extension modules in bdist_dir, since the user can specify
# a higher MACOSX_DEPLOYMENT_TARGET via tools like CMake
# on other platforms, and on macosx if there are no c-extension
# modules, use the default platform name.
plat_name = get_platform(self.bdist_dir)
if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647:
plat_name = 'linux_i686'
# To allow uploading to pypi, we need the wheel name
# to contain 'manylinux1'.
# The wheel which will be uploaded to pypi will be
# built on RHEL7, so it doesn't completely qualify for
# manylinux1 support, but it's the minimum requirement
# for building Qt. We only enable this for x64 limited
# api builds (which are the only ones uploaded to
# pypi).
# TODO: Add actual distro detection, instead of
# relying on limited_api option.
if (plat_name in ('linux-x86_64', 'linux_x86_64')
and sys.maxsize > 2147483647
and (self.py_limited_api or sys.version_info[0] == 2)):
plat_name = 'manylinux1_x86_64'
plat_name = plat_name.replace('-', '_').replace('.', '_')
if self.root_is_pure:
if self.universal:
impl = 'py2.py3'
else:
impl = self.python_tag
tag = (impl, 'none', plat_name)
else:
impl_name = tags.interpreter_name()
impl_ver = tags.interpreter_version()
impl = impl_name + impl_ver
# We don't work on CPython 3.1, 3.0.
if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'):
impl = self.py_limited_api
abi_tag = "abi3" if sys.platform != "win32" else "none"
else:
abi_tag = str(get_abi_tag()).lower()
tag = (impl, abi_tag, plat_name)
supported_tags = [(t.interpreter, t.abi, t.platform)
for t in tags.sys_tags()]
# XXX switch to this alternate implementation for non-pure:
if (self.py_limited_api) or (plat_name in ('manylinux1_x86_64') and sys.version_info[0] == 2):
return tag
assert tag in supported_tags, ("would build wheel with unsupported tag {}".format(tag))
return tag
# Copy of get_tag from bdist_wheel.py, to write a triplet Tag
# only once for the limited_api case.
def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'):
from email.message import Message
msg = Message()
msg['Wheel-Version'] = '1.0' # of the spec
msg['Generator'] = generator
msg['Root-Is-Purelib'] = str(self.root_is_pure).lower()
if self.build_number is not None:
msg['Build'] = self.build_number
# Doesn't work for bdist_wininst
impl_tag, abi_tag, plat_tag = self.get_tag()
# To enable pypi upload we are adjusting the wheel name
pypi_ready = (OPTION["LIMITED_API"] and sys.version_info[0] >= 3) or (sys.version_info[0] == 2)
def writeTag(impl):
for abi in abi_tag.split('.'):
for plat in plat_tag.split('.'):
msg['Tag'] = '-'.join((impl, abi, plat))
if pypi_ready:
writeTag(impl_tag)
else:
for impl in impl_tag.split('.'):
writeTag(impl)
wheelfile_path = os.path.join(wheelfile_base, 'WHEEL')
logger.info('creating %s', wheelfile_path)
with open(wheelfile_path, 'w') as f:
Generator(f, maxheaderlen=0).flatten(msg)
if not wheel_module_exists:
del PysideBuildWheel
build_scripts/wheel_utils.py 0000664 0000000 0000000 00000014373 13766170131 0016637 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import time
from distutils.errors import DistutilsSetupError
from distutils.sysconfig import get_config_var
from distutils.util import get_platform
from distutils.version import LooseVersion
from .options import OPTION
from .qtinfo import QtInfo
from .utils import memoize, get_python_dict
@memoize
def get_package_timestamp():
""" In a Coin CI build the returned timestamp will be the
Coin integration id timestamp. For regular builds it's
just the current timestamp or a user provided one."""
option_value = OPTION["PACKAGE_TIMESTAMP"]
return option_value if option_value else int(time.time())
def get_qt_version():
qtinfo = QtInfo()
qt_version = qtinfo.version
if not qt_version:
m = "Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command)
raise DistutilsSetupError(m)
if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
m = "Incompatible Qt version detected: {}. A Qt version >= 5.7 is required.".format(qt_version)
raise DistutilsSetupError(m)
return qt_version
@memoize
def get_package_version():
""" Returns the version string for the PySide2 package. """
setup_script_dir = os.getcwd()
pyside_version_py = os.path.join(
setup_script_dir, "sources", "pyside2", "pyside_version.py")
d = get_python_dict(pyside_version_py)
final_version = "{}.{}.{}".format(
d['major_version'], d['minor_version'], d['patch_version'])
release_version_type = d['release_version_type']
pre_release_version = d['pre_release_version']
if pre_release_version and release_version_type:
final_version += release_version_type + pre_release_version
if release_version_type.startswith("comm"):
final_version += "." + release_version_type
# Add the current timestamp to the version number, to suggest it
# is a development snapshot build.
if OPTION["SNAPSHOT_BUILD"]:
final_version += ".dev{}".format(get_package_timestamp())
return final_version
def macos_qt_min_deployment_target():
target = QtInfo().macos_min_deployment_target
if not target:
raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.")
return target
@memoize
def macos_pyside_min_deployment_target():
"""
Compute and validate PySide2 MACOSX_DEPLOYMENT_TARGET value.
Candidate sources that are considered:
- setup.py provided value
- maximum value between minimum deployment target of the
Python interpreter and the minimum deployment target of
the Qt libraries.
If setup.py value is provided, that takes precedence.
Otherwise use the maximum of the above mentioned two values.
"""
python_target = get_config_var('MACOSX_DEPLOYMENT_TARGET') or None
qt_target = macos_qt_min_deployment_target()
setup_target = OPTION["MACOS_DEPLOYMENT_TARGET"]
qt_target_split = [int(x) for x in qt_target.split('.')]
if python_target:
python_target_split = [int(x) for x in python_target.split('.')]
if setup_target:
setup_target_split = [int(x) for x in setup_target.split('.')]
message = ("Can't set MACOSX_DEPLOYMENT_TARGET value to {} because "
"{} was built with minimum deployment target set to {}.")
# setup.py provided OPTION["MACOS_DEPLOYMENT_TARGET"] value takes
# precedence.
if setup_target:
if python_target and setup_target_split < python_target_split:
raise DistutilsSetupError(message.format(setup_target, "Python",
python_target))
if setup_target_split < qt_target_split:
raise DistutilsSetupError(message.format(setup_target, "Qt",
qt_target))
# All checks clear, use setup.py provided value.
return setup_target
# Setup.py value not provided,
# use same value as provided by Qt.
if python_target:
maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)])
else:
maximum_target = qt_target
return maximum_target
@memoize
def macos_plat_name():
deployment_target = macos_pyside_min_deployment_target()
# Example triple "macosx-10.12-x86_64".
plat = get_platform().split("-")
plat_name = "{}-{}-{}".format(plat[0], deployment_target, plat[2])
return plat_name
coin/ 0000775 0000000 0000000 00000000000 13766170131 0012013 5 ustar 00root root 0000000 0000000 coin/instructions/ 0000775 0000000 0000000 00000000000 13766170131 0014557 5 ustar 00root root 0000000 0000000 coin/instructions/common_environment.yaml 0000664 0000000 0000000 00000006750 13766170131 0021367 0 ustar 00root root 0000000 0000000 type: Group
instructions:
- type: EnvironmentVariable
variableName: TARGET_ARCHITECTURE
variableValue: amd64
enable_if:
condition: and
conditions:
- condition: property
property: target.arch
equals_value: X86_64
- condition: property
property: host.os
equals_value: Windows
- type: EnvironmentVariable
variableName: TARGET_ARCHITECTURE
variableValue: amd64_x86
enable_if:
condition: and
conditions:
- condition: property
property: target.arch
equals_value: X86
- condition: property
property: host.os
equals_value: Windows
- type: EnvironmentVariable
variableName: CI_TARGET_ARCHITECTURE
variableValue: X86_64
enable_if:
condition: property
property: target.arch
equals_value: X86_64
- type: EnvironmentVariable
variableName: CI_TARGET_ARCHITECTURE
variableValue: X86
enable_if:
condition: property
property: target.arch
equals_value: X86
- type: EnvironmentVariable
variableName: CI_PACKAGING_FEATURE
variableValue: "--packaging"
enable_if:
condition: property
property: features
contains_value: Packaging
- type: EnvironmentVariable
variableName: CI_OS
variableValue: "MacOS"
enable_if:
condition: property
property: host.os
equals_value: MacOS
- type: EnvironmentVariable
variableName: CI_OS
variableValue: "Linux"
enable_if:
condition: property
property: host.os
equals_value: Linux
- type: EnvironmentVariable
variableName: CI_OS
variableValue: "Windows"
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: EnvironmentVariable
variableName: MAKEFLAGS
variableValue: ""
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: AppendToEnvironmentVariable
variableName: PATH
variableValue: ;%CI_JOM_PATH%
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: PrependToEnvironmentVariable
variableName: PATH
variableValue: "\\Users\\qt\\work\\install\\bin;"
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: EnvironmentVariable
variableName: ICC64_18_LDLP
variableValue: /opt/intel/lib/intel64
enable_if:
condition: property
property: target.compiler
equals_value: ICC_18
- type: EnvironmentVariable
variableName: ICC64_18_PATH # Seems a bit hard to maintain
variableValue: /opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:/opt/intel/bin
enable_if:
condition: property
property: target.compiler
equals_value: ICC_18
- type: AppendToEnvironmentVariable
variableName: LD_LIBRARY_PATH
variableValue: :/opt/intel/lib/intel64
enable_if:
condition: property
property: target.compiler
equals_value: ICC_18
- type: AppendToEnvironmentVariable
variableName: PATH
variableValue: ":{{.Env.ICC64_18_PATH}}"
enable_if:
condition: property
property: target.compiler
equals_value: ICC_18
coin/instructions/execute_build_instructions.yaml 0000664 0000000 0000000 00000004661 13766170131 0023117 0 ustar 00root root 0000000 0000000 type: Group
instructions:
- type: ExecuteCommand
command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=ALL"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 1200
enable_if:
condition: property
property: host.os
equals_value: MacOS
userMessageOnFailure: >
Failed to execute build instructions on osx
- type: ExecuteCommand
command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/home/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=ALL"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 600
enable_if:
condition: property
property: host.os
equals_value: Linux
userMessageOnFailure: >
Failed to execute build instructions on Linux
- type: ExecuteCommand
command: "c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=BUILD"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 600
enable_if:
condition: property
property: host.os
equals_value: Windows
userMessageOnFailure: >
Failed to execute build instructions on Windows
- type: SignPackage
directory: "{{.AgentWorkingDir}}\\pyside"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: ChangeDirectory
directory: "{{.AgentWorkingDir}}\\pyside\\pyside-setup"
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: ExecuteCommand
command: "c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=WHEEL"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 300
enable_if:
condition: property
property: host.os
equals_value: Windows
userMessageOnFailure: >
Failed to create wheels for Windows
coin/instructions/execute_license_check.yaml 0000664 0000000 0000000 00000002067 13766170131 0021751 0 ustar 00root root 0000000 0000000 type: Group
instructions:
- type: ChangeDirectory
directory: "{{.AgentWorkingDir}}"
- type: InstallSourceArchive
maxTimeInSeconds: 600
maxTimeBetweenOutput: 600
project: qt/qtbase
ref: 5.15
directory: qt/qtbase
userMessageOnFailure: >
Could not install source archive. Please investigate why.
- type: InstallSourceArchive
maxTimeInSeconds: 600
maxTimeBetweenOutput: 600
project: qt/qtqa
ref: master
directory: qt/qtqa-latest
userMessageOnFailure: >
Could not install source archive. Please investigate why.
- type: EnvironmentVariable
variableName: QT_MODULE_TO_TEST
variableValue: pyside/pyside-setup
userMessageOnFailure: >
Failed to set environment variable. This should not happen.
- type: ExecuteCommand
command: perl qt/qtqa-latest/tests/prebuild/license/tst_licenses.pl
maxTimeInSeconds: 7200
maxTimeBetweenOutput: 120
userMessageOnFailure: >
Failed to run license check script.
coin/instructions/execute_test_instructions.yaml 0000664 0000000 0000000 00000003241 13766170131 0022770 0 ustar 00root root 0000000 0000000 type: Group
enable_if:
condition: property
property: features
not_contains_value: LicenseCheck
instructions:
- type: EnvironmentVariable
variableName: QTEST_ENVIRONMENT
variableValue: "ci"
- type: ExecuteCommand
command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 1200
enable_if:
condition: property
property: host.os
equals_value: MacOS
userMessageOnFailure: >
Failed to execute test instructions on osx
- type: ExecuteCommand
command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/home/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 600
enable_if:
condition: property
property: host.os
equals_value: Linux
userMessageOnFailure: >
Failed to execute test instructions on Linux
- type: ExecuteCommand
command: "c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 600
enable_if:
condition: property
property: host.os
equals_value: Windows
userMessageOnFailure: >
Failed to execute test instructions on 64 bit Windows
coin/instructions/find_path_to_msvc_compiler.yaml 0000664 0000000 0000000 00000001637 13766170131 0023032 0 ustar 00root root 0000000 0000000 type: Group
enable_if:
condition: property
property: host.os
equals_value: Windows
instructions:
- type: EnvironmentVariable
variableName: VC_SCRIPT
variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2017\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat"
enable_if:
condition: property
property: host.compiler
equals_value: MSVC2017
- type: EnvironmentVariable
variableName: VC_SCRIPT
variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2019\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat"
enable_if:
condition: property
property: host.compiler
equals_value: MSVC2019
- type: WriteFile
fileContents: "call \"{{.Env.VC_SCRIPT}}\" {{.Env.TARGET_ARCHITECTURE}} \r\ncmd /c %*"
filename: "c:\\users\\qt\\MSVC.bat"
fileMode: 420
enable_if:
condition: property
property: host.os
equals_value: Windows
coin/instructions/relocate_pyside.yaml 0000664 0000000 0000000 00000003276 13766170131 0020626 0 ustar 00root root 0000000 0000000 type: Group
enable_if:
condition: property
property: features
not_contains_value: LicenseCheck
instructions:
- type: ChangeDirectory
directory: "{{.AgentWorkingDir}}/pyside"
maxTimeInSeconds: 300
maxTimeBetweenOutput: 120
userMessageOnFailure: >
Failed to change to pyside dir
- type: ExecuteCommand
command: c:\\users\\qt\\MSVC.bat rd /s /q pyside-setup
maxTimeInSeconds: 300
maxTimeBetweenOutput: 120
enable_if:
condition: property
property: host.os
equals_value: Windows
userMessageOnFailure: >
Failed to remove pyside-setup dir
- type: ExecuteCommand
command: /bin/rm -rf pyside-setup
maxTimeInSeconds: 300
maxTimeBetweenOutput: 120
enable_if:
condition: property
property: host.os
not_equals_value: Windows
userMessageOnFailure: >
Failed to remove pyside-setup dir
- type: InstallBinaryArchive
relativeStoragePath: "{{.Env.MODULE_ARTIFACTS_RELATIVE_STORAGE_PATH}}/artifacts.tar.gz"
directory: "pyside"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
- type: ChangeDirectory
directory: "{{.AgentWorkingDir}}\\pyside\\pyside-setup"
maxTimeInSeconds: 7200
maxTimeBetweenOutput: 120
enable_if:
condition: property
property: host.os
equals_value: Windows
userMessageOnFailure: >
Failed to install binary artifacts
- type: ChangeDirectory
directory: "{{.AgentWorkingDir}}/pyside/pyside-setup"
maxTimeInSeconds: 7200
maxTimeBetweenOutput: 120
enable_if:
condition: property
property: host.os
not_equals_value: Windows
userMessageOnFailure: >
Failed to change to pyside-setup dir
coin/module_config.yaml 0000664 0000000 0000000 00000005101 13766170131 0015506 0 ustar 00root root 0000000 0000000 version: 2
accept_configuration:
condition: or
conditions:
- condition: and
conditions:
- condition: property # No cross compilation
property: host.os
equals_property: target.os
- condition: property # qtnamespace is not supported
property: configureArgs
not_contains_value: -qtnamespace
- condition: property # no-widgets is notsupported
property: configureArgs
not_contains_value: -no-widgets
- condition: property # no-gui is not supported
property: configureArgs
not_contains_value: -no-gui
- condition: property # Following configs are not supported
property: target.osVersion
not_in_values: [OPENSUSE_13_01, QEMU, WebAssembly, Ubuntu_18_04, SLES_12, SLES_15]
- condition: property # MibnGW and msvc2015 are not supported
property: target.compiler
not_in_values: [Mingw, MSVC2015]
- condition: and
conditions:
- condition: property
property: target.osVersion
equals_value: Ubuntu_18_04
- condition: property
property: features
contains_value: LicenseCheck
upload_pyside: &upload_pyside
type: Group
instructions:
- type: UploadArtifact
archiveDirectory: "{{.AgentWorkingDir}}\\pyside"
transferType: UploadModuleBuildArtifact
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
enable_if:
condition: property
property: host.os
equals_value: Windows
- type: UploadArtifact
archiveDirectory: "{{.AgentWorkingDir}}/pyside"
transferType: UploadModuleBuildArtifact
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
enable_if:
condition: property
property: host.os
not_equals_value: Windows
instructions:
LicenseCheck:
- !include "{{pyside/pyside-setup}}/execute_license_check.yaml"
Build:
- !include "{{pyside/pyside-setup}}/common_environment.yaml"
- !include "{{pyside/pyside-setup}}/find_path_to_msvc_compiler.yaml"
- !include "{{pyside/pyside-setup}}/execute_build_instructions.yaml"
- *upload_pyside
Test:
- !include "{{pyside/pyside-setup}}/common_environment.yaml"
- !include "{{pyside/pyside-setup}}/find_path_to_msvc_compiler.yaml"
- !include "{{pyside/pyside-setup}}/relocate_pyside.yaml"
- !include "{{pyside/pyside-setup}}/execute_test_instructions.yaml"
coin_build_instructions.py 0000664 0000000 0000000 00000016667 13766170131 0016410 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from build_scripts.options import has_option
from build_scripts.options import option_value
from build_scripts.utils import install_pip_dependencies
from build_scripts.utils import get_qtci_virtualEnv
from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
from build_scripts.utils import get_python_dict
from build_scripts.utils import get_ci_qmake_path
import os
import datetime
import calendar
import site
import sys
# Values must match COIN thrift
CI_HOST_OS = option_value("os")
CI_TARGET_OS = option_value("targetOs")
CI_HOST_ARCH = option_value("hostArch")
CI_TARGET_ARCH = option_value("targetArch")
CI_HOST_OS_VER = option_value("osVer")
CI_ENV_INSTALL_DIR = option_value("instdir")
CI_ENV_AGENT_DIR = option_value("agentdir")
CI_COMPILER = option_value("compiler")
CI_INTEGRATION_ID = option_value("coinIntegrationId") or str(calendar.timegm(datetime.datetime.now().timetuple()))
CI_FEATURES = []
_ci_features = option_value("features")
if _ci_features is not None:
for f in _ci_features.split(', '):
CI_FEATURES.append(f)
CI_RELEASE_CONF = has_option("packaging")
CI_TEST_PHASE = option_value("phase")
if CI_TEST_PHASE not in ["ALL", "BUILD", "WHEEL"]:
CI_TEST_PHASE = "ALL"
def get_current_script_path():
""" Returns the absolute path containing this script. """
try:
this_file = __file__
except NameError:
this_file = sys.argv[0]
this_file = os.path.abspath(this_file)
return os.path.dirname(this_file)
def is_snapshot_build():
"""
Returns True if project needs to be built with --snapshot-build
This is true if the version found in pyside_version.py is not a
pre-release version (no alphas, betas).
This eliminates the need to remove the --snapshot-build option
on a per-release branch basis (less things to remember to do
for a release).
"""
setup_script_dir = get_current_script_path()
pyside_version_py = os.path.join(
setup_script_dir, "sources", "pyside2", "pyside_version.py")
d = get_python_dict(pyside_version_py)
release_version_type = d['release_version_type']
pre_release_version = d['pre_release_version']
if pre_release_version and release_version_type:
return True
return False
def call_setup(python_ver, phase):
print("call_setup")
print("python_ver", python_ver)
print("phase", phase)
_pExe, _env, env_pip, env_python = get_qtci_virtualEnv(python_ver, CI_HOST_OS, CI_HOST_ARCH, CI_TARGET_ARCH)
if phase in ["BUILD"]:
rmtree(_env, True)
# Pinning the virtualenv before creating one
run_instruction(["pip", "install", "--user", "virtualenv==20.0.25"], "Failed to pin virtualenv")
# installing to user base might not be in PATH by default.
env_path = os.path.join(site.USER_BASE, "bin")
v_env = os.path.join(env_path, "virtualenv")
if sys.platform == "win32":
env_path = os.path.join(site.USER_BASE, "Scripts")
v_env = os.path.join(env_path, "virtualenv.exe")
try:
run_instruction([v_env, "--version"], "Using default virtualenv")
except Exception as e:
v_env = "virtualenv"
run_instruction([v_env, "-p", _pExe, _env], "Failed to create virtualenv")
# When the 'python_ver' variable is empty, we are using Python 2
# Pip is always upgraded when CI template is provisioned, upgrading it in later phase may cause perm issue
run_instruction([env_pip, "install", "-r", "requirements.txt"], "Failed to install dependencies")
if sys.platform == "win32":
run_instruction([env_pip, "install", "numpy==1.19.3"], "Failed to install numpy 1.19.3")
else:
run_instruction([env_pip, "install", "numpy"], "Failed to install numpy")
cmd = [env_python, "-u", "setup.py"]
if phase in ["BUILD"]:
cmd += ["build", "--standalone", "--skip-packaging"]
elif phase in ["WHEEL"] or CI_RELEASE_CONF:
cmd += ["bdist_wheel", "--reuse-build", "--standalone", "--skip-cmake", "--skip-make-install", "--only-package"]
cmd += ["--build-tests",
"--parallel=4",
"--verbose-build"]
if python_ver == "3":
cmd += ["--limited-api=yes"]
if is_snapshot_build():
cmd += ["--snapshot-build"]
qmake_path = get_ci_qmake_path(CI_ENV_INSTALL_DIR, CI_HOST_OS)
cmd.append(qmake_path)
# Due to certain older CMake versions generating very long paths
# (at least with CMake 3.6.2) when using the export() function,
# pass the shorter paths option on Windows so we don't hit
# the path character length limit (260).
if CI_HOST_OS == "Windows":
cmd += ["--shorter-paths"]
cmd += ["--package-timestamp=" + CI_INTEGRATION_ID]
env = os.environ
run_instruction(cmd, "Failed to run setup.py for build", initial_env=env)
def run_build_instructions(phase):
# Uses default python, hopefully we have python2 installed on all hosts
# Skip building using Python 2 on Windows, because of different MSVC C runtimes (VS2008 vs VS2015+)
if CI_HOST_OS != "Windows":
call_setup("", phase)
# In case of packaging build, we have to build also python3 wheel
if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]:
call_setup("3", phase)
if __name__ == "__main__":
# Remove some environment variables that impact cmake
for env_var in ['CC', 'CXX']:
if os.environ.get(env_var):
del os.environ[env_var]
if CI_TEST_PHASE in ["ALL", "BUILD"]:
run_build_instructions("BUILD")
if CI_TEST_PHASE in ["ALL", "WHEEL"]:
run_build_instructions("WHEEL")
coin_test_instructions.py 0000664 0000000 0000000 00000012655 13766170131 0016261 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2019 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
from build_scripts.options import has_option
from build_scripts.options import option_value
from build_scripts.utils import install_pip_dependencies
from build_scripts.utils import get_qtci_virtualEnv
from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
from build_scripts.utils import get_ci_qmake_path
import os
import site
import sys
# Values must match COIN thrift
CI_HOST_OS = option_value("os")
CI_TARGET_OS = option_value("targetOs")
CI_HOST_ARCH = option_value("hostArch")
CI_TARGET_ARCH = option_value("targetArch")
CI_HOST_OS_VER = option_value("osVer")
CI_ENV_INSTALL_DIR = option_value("instdir")
CI_ENV_AGENT_DIR = option_value("agentdir") or "."
CI_COMPILER = option_value("compiler")
CI_FEATURES = []
_ci_features = option_value("features")
if _ci_features is not None:
for f in _ci_features.split(', '):
CI_FEATURES.append(f)
CI_RELEASE_CONF = has_option("packaging")
def call_testrunner(python_ver, buildnro):
_pExe, _env, env_pip, env_python = get_qtci_virtualEnv(python_ver, CI_HOST_OS, CI_HOST_ARCH, CI_TARGET_ARCH)
rmtree(_env, True)
# Pinning the virtualenv before creating one
run_instruction(["pip", "install", "--user", "virtualenv==20.0.25"], "Failed to pin virtualenv")
# installing to user base might not be in PATH by default.
env_path = os.path.join(site.USER_BASE, "bin")
v_env = os.path.join(env_path, "virtualenv")
if sys.platform == "win32":
env_path = os.path.join(site.USER_BASE, "Scripts")
v_env = os.path.join(env_path, "virtualenv.exe")
try:
run_instruction([v_env, "--version"], "Using default virtualenv")
except Exception as e:
v_env = "virtualenv"
run_instruction([v_env, "-p", _pExe, _env], "Failed to create virtualenv")
# When the 'python_ver' variable is empty, we are using Python 2
# Pip is always upgraded when CI template is provisioned, upgrading it in later phase may cause perm issue
run_instruction([env_pip, "install", "-r", "requirements.txt"], "Failed to install dependencies")
if sys.platform == "win32":
run_instruction([env_pip, "install", "numpy==1.19.3"], "Failed to install numpy 1.19.3")
else:
run_instruction([env_pip, "install", "numpy"], "Failed to install numpy")
cmd = [env_python, "testrunner.py", "test",
"--blacklist", "build_history/blacklist.txt",
"--buildno=" + buildnro]
run_instruction(cmd, "Failed to run testrunner.py")
qmake_path = get_ci_qmake_path(CI_ENV_INSTALL_DIR, CI_HOST_OS)
# Try to install built wheels, and build some buildable examples.
if CI_RELEASE_CONF:
wheel_tester_path = os.path.join("testing", "wheel_tester.py")
cmd = [env_python, wheel_tester_path, qmake_path]
run_instruction(cmd, "Error while running wheel_tester.py")
def run_test_instructions():
# Remove some environment variables that impact cmake
for env_var in ['CC', 'CXX']:
if os.environ.get(env_var):
del os.environ[env_var]
os.chdir(CI_ENV_AGENT_DIR)
testRun = 0
# We didn't build for Python 2 in win
if CI_HOST_OS != "Windows":
call_testrunner("", str(testRun))
testRun =+ 1
# We know that second build was with python3
if CI_RELEASE_CONF:
# In win machines, there are additional python versions to test with
if CI_HOST_OS == "Windows":
call_testrunner("3.6.1", str(testRun))
call_testrunner("3.8.1", str(testRun))
else:
call_testrunner("3", str(testRun))
if __name__ == "__main__":
run_test_instructions()
dist/ 0000775 0000000 0000000 00000000000 13766170131 0012026 5 ustar 00root root 0000000 0000000 dist/changes-1.2.3 0000664 0000000 0000000 00000037011 13766170131 0014022 0 ustar 00root root 0000000 0000000 Changes
=======
1.2.3 (2014-??-??)
------------------
Major changes
~~~~~~~~~~~~~
PySide-setup
************
- On Linux systems there is no more need to call the post-install script
1.2.2 (2014-04-24)
------------------
Complete list of changes and bug fixes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PySide
******
- Fix PYSIDE-190: QCoreApplication would deadlock on exit if the global
QThreadPool.globalInstance() is running a QRunnable with python code
- Change GlobalReceiver to explicitly 'use' [dis]connectNotify of the base
class in order to avoid hiding these with its own overloads.
- Add explicit casts when initializing an int[] using {}'s, as required
by C++11 to be "well formed"
- Fix PYSIDE-172: multiple rules for file
- Use file system encoding instead of assumed 'ascii' when registering
qt.conf in Qt resource system
Shiboken
********
- Remove rejection lines that cause the sample_list test to fail
- Remove protected from samblebinding test
- Add parsing of 'noexcept' keyword
- Fix function rejections (i.e. support overloads)
- Fix building with python 3.3 and 3.4
- Doc: Stop requiring sphinx.ext.refcounting with Sphinx 1.2+
- Fix for containers with 'const' values
- Fix compilation issue on OS X 10.9
- Only use fields in PyTypeObject when defining types
- Fix buffer overrun processing macro definitions
- Fix 'special' include handling
- Fix finding container base classes
- Refactor and improve added function resolving
- Work around MSVC's deficient in libsample/transform.cpp
- Fix description of sample/transform unit test
- Change wrapping and indent of some code in Handler::startElement to
improve consistency
- Fix '%#' substitution for # > 9
- Improve dependencies for tests
1.2.1 (2013-08-16)
------------------
Major changes
~~~~~~~~~~~~~
PySide
******
- In memory qt.conf generation and registration
Shiboken
********
- Better support for more than 9 arguments to methods
- Avoiding a segfault when getting the .name attribute on an enum value with no name
PySide-setup
************
- Switched to the new setuptools (v0.9.8) which has been merged with Distribute again and works for Python 2 and 3 with one codebase
- Support for building windows binaries with only Windows SDK installed (Visual Studio is no more required)
- Removed --msvc-version option. Required msvc compiler version is now resolved from python interpreter version
1.2.0 (2013-07-02)
------------------
Major changes
~~~~~~~~~~~~~
PySide
******
- Fix multiple segfaults and better track the life time of Qt objects
- Fix multiple memory leaks
Shiboken
********
- Install the shiboken module to site-packages
- Fix multiple segfaults
PySide-setup
************
- On Windows system, when installing PySide binary distribution via easy_install,
there is no more need to call the post-install script
- Support for building windows binaries outside of Visual Studio command prompt
- Build and package the shiboken docs when sphinx is installed
Complete list of changes and bug fixes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PySide
******
- Set up PYTHONPATH for tests correctly
- Fix potential segfault at shutdown
- Fix PYSIDE-61
- Tell Qt to look for qml imports in the PySide package
- fix build in C++11 mode
- Fix QByteArray memory leak
- Ignore QtCore import errors when initializing plugins folder
- Preload OpenSSL DLLs on Windows.
- Look first in the PySide package for Qt's plugins folder, instead of just in Qt's install or build folder
- Add explicit type conversion to fix mingw compile error
- Use QObject property to invalidate wrapper before deletion
- Invalidate metaObject wrapper before deletion
- Fix reference leak on convertion from a C++ map type to Python dict
- Change the order of pysitetest and signals directories because signals/disconnect_test.py depends on pysidetest module
Shiboken
********
- Removed old logos from html docs
- Add missing return on module init error
- Don't break -Werror=non-virtual-dtor
- Fixing shiboken test for minimal binding test
- Decref reference to type object
- Fix segfault when using shiboken.delete
- Use non-static method def for instance methods
- Fix bug introduced when recursive_invalidate was added
- fix build in C++11 mode
- Prevent infinite recursion in invalidate
- Fix possible conflict with garbage collector
- Fix possible crash at exit
- Fix handling of unsigned long long and provide unittests
- Add test to illustrate issue on typedef enum
- Use getWrapperForQObject to convert if generating for PySide
- Allow compilation without a python shared library
- Use parent class's metaObject if wrapper is NULL
- Optionally assert on free'd pointer with a valid wrapper
- Find python3 libraries when built with pydebug enabled
- Fix PYSIDE-108 bug and add example
- PYSIDE-83 Fix segfault calling shiboken.dump
- Fix and test case for bug PYSIDE-72
- Override all functions with the same name, not just one
- Update vector conversion
- Add typedef examples to minimal
- Add test files back to cmake
- Don't use it->second after erasing it
- Find function modifications defined in the 2nd+ base class. Fixes bug PYSIDE-54.
- Set a default hash function for all ObjectTypes. Fix bug PYSIDE-42.
- Fix compilation when there is no libxslt installed on the system.
- Fixed resolving of SOABI. SOABI is implemented on Linux, but not on Windows
- Don't use inline methods in dllexported classes to keep VC++ happy
- Use SpooledTemporaryFile in 2.6+ os.tmpfile() fails on win32 if process doesn't have admin permissions
PySide-setup
************
- Support for building windows binaries outside of Visual Studio command prompt
- Build and package the shiboken docs when sphinx is installed
- Support Ubuntu 13.04 and Fedora 18
- Fixed "develop" setuptools command
- Documentation updates
- Add --build-tests option to enable building the tests
- Add --jom and --jobs options
- Add --no-examples option to exclude the examples
- Add --relwithdebinfo option to enable a release-with-debug-info build mode
- Add --ignore-git option
- Add --make-spec option to specify make generator
1.1.2 (2012-08-28)
------------------
Bug fixes
~~~~~~~~~
- During signal emission don't get return type after callback
- Invalidate QStandardModel::invisibleRootItem in clear() method
- QAbstractItemModel has wrong ownership policy for selectionModel()
- Improved QVector to python conversion
- Disable docstring generation if tools aren't found.
- Fixed some issues compiling PySide using VC++
- Install the shiboken module to site-packages
- Fix compilation when there is no libxslt installed on the system.
- Set a default hash function for all ObjectTypes.
- Fix segfault calling shiboken.dump
1.1.1 (2012-04-19)
------------------
Major changes
~~~~~~~~~~~~~
- Unified toolchain! No more GeneratorRunner and ApiExtractor, now you just need Shiboken to compile PySide.
Bug fixes
~~~~~~~~~
- 1105 Spyder fails with HEAD
- 1126 Segfault when exception is raised in signalInstanceDisconnect
- 1135 SIGSEGV when loading custom widget using QUiLoader when overriding createWidget()
- 1041 QAbstractItemModel has wrong ownership policy for selectionModel()
- 1086 generatorrunner segfault processing #include
- 1110 Concurrency error causes GC heap corruption
- 1113 Instantiating QObject in user-defined QML element's constructor crashes if instantiated from QML
- 1129 Segmentation fault on close by QStandardItem/QStandardItemModel
- 1104 QSettings has problems with long integers
- 1108 tests/QtGui/pyside_reload_test.py fails when bytecode writing is disabled
- 1138 Subclassing of QUiLoader leads to "Internal C++ object already deleted" exception (again)
- 1124 QPainter.drawPixmapFragments should take a list as first argument
- 1065 Invalid example in QFileDialog documentation
- 1092 shiboken names itself a 'generator'
- 1094 shiboken doesn't complain about invalid options
- 1044 Incorrect call to parent constructor in example
- 1139 Crash at exit due to thread state (tstate) being NULL
- PYSIDE-41 QModelIndex unhashable
1.1.0 (2012-01-02)
------------------
Major changes
~~~~~~~~~~~~~
- New type converter scheme
Bug fixes
~~~~~~~~~
- 1010 Shiboken Cygwin patch
- 1034 Error compiling PySide with Python 3.2.2 32bit on Windows
- 1040 pyside-uic overwriting attributes before they are being used
- 1053 pyside-lupdate used with .pro files can't handle Windows paths that contain spaces
- 1060 Subclassing of QUiLoader leads to "Internal C++ object already deleted" exception
- 1063 Bug writing to files using "QTextStream + QFile + QTextEdit" on Linux
- 1069 QtCore.QDataStream silently fails on writing Python string
- 1077 Application exit crash when call QSyntaxHighlighter.document()
- 1082 OSX binary links are broken
- 1083 winId returns a PyCObject making it impossible to compare two winIds
- 1084 Crash (segfault) when writing unicode string on socket
- 1091 PixmapFragment and drawPixmapFragments are not bound
- 1095 No examples for shiboken tutorial
- 1097 QtGui.QShortcut.setKey requires QKeySequence
- 1101 Report invalid function signatures in typesystem
- 902 Expose Shiboken functionality through a Python module
- 969 viewOptions of QAbstractItemView error
1.0.9 (2011-11-29)
------------------
Bug fixes
~~~~~~~~~
- 1058 Strange code in PySide/QtUiTools/glue/plugins.h
- 1057 valgrind detected "Conditional jump or move depends on uninitialised value"
- 1052 PySideConfig.cmake contains an infinite loop due to missing default for SHIBOKEN_PYTHON_SUFFIX
- 1048 QGridLayout.itemAtPosition() crashes when it should return None
- 1037 shiboken fails to build against python 3.2 (both normal and -dbg) on i386 (and others)
- 1036 Qt.KeyboardModifiers always evaluates to zero
- 1033 QDialog.DialogCode instances and return value from \QDialog.exec_ hash to different values
- 1031 QState.parentState() or QState.machine() causes python crash at exit
- 1029 qmlRegisterType Fails to Increase the Ref Count
- 1028 QWidget winId missing
- 1016 Calling of Q_INVOKABLE method returning not QVariant is impossible...
- 1013 connect to QSqlTableModel.primeInsert() causes crash
- 1012 FTBFS with hardening flags enabled
- 1011 PySide Cygwin patch
- 1010 Shiboken Cygwin patch
- 1009 GeneratorRunner Cygwin patch
- 1008 ApiExtractor Cygwin patch
- 891 ApiExtractor doesn't support doxygen as backend to doc generation.
1.0.8 (2011-10-21)
------------------
Major changes
~~~~~~~~~~~~~
- Experimental Python3.2 support
- Qt4.8 beta support
Bug fixes
~~~~~~~~~
- 1022 RuntimeError: maximum recursion depth exceeded while getting the str of an object
- 1019 Overriding QWidget.show or QWidget.hide do not work
- 944 Segfault on QIcon(None).pixmap()
1.0.7 (2011-09-21)
------------------
Bug fixes
~~~~~~~~~
- 996 Missing dependencies for QtWebKit in buildscripts for Fedora
- 986 Documentation links
- 985 Provide versioned pyside-docs zip file to help packagers
- 981 QSettings docs should empathize the behavior changes of value() on different platforms
- 902 Expose Shiboken functionality through a Python module
- 997 QDeclarativePropertyMap doesn't work.
- 994 QIODevice.readData must use qmemcpy instead of qstrncpy
- 989 Pickling QColor fails
- 987 Disconnecting a signal that has not been connected
- 973 shouldInterruptJavaScript slot override is never called
- 966 QX11Info.display() missing
- 959 can't pass QVariant to the QtWebkit bridge
- 1006 Segfault in QLabel init
- 1002 Segmentation fault on PySide/Spyder exit
- 998 Segfault with Spyder after switching to another app
- 995 QDeclarativeView.itemAt returns faulty reference. (leading to SEGFAULT)
- 990 Segfault when trying to disconnect a signal that is not connected
- 975 Possible memory leak
- 991 The __repr__ of various types is broken
- 988 The type supplied with currentChanged signal in QTabWidget has changed in 1.0.6
1.0.6 (2011-08-22)
------------------
Major changes
~~~~~~~~~~~~~
- New documentation layout;
- Fixed some regressions from the last release (1.0.5);
- Optimizations during anonymous connection;
Bug fixes
~~~~~~~~~
- 972 anchorlayout.py of graphicsview example raised a unwriteable memory exception when exits
- 953 Segfault when QObject is garbage collected after QTimer.singeShot
- 951 ComponentComplete not called on QDeclarativeItem subclass
- 965 Segfault in QtUiTools.QUiLoader.load
- 958 Segmentation fault with resource files
- 944 Segfault on QIcon(None).pixmap()
- 941 Signals with QtCore.Qt types as arguments has invalid signatures
- 964 QAbstractItemView.moveCursor() method is missing
- 963 What's This not displaying QTableWidget column header information as in Qt Designer
- 961 QColor.__repr__/__str__ should be more pythonic
- 960 QColor.__reduce__ is incorrect for HSL colors
- 950 implement Q_INVOKABLE
- 940 setAttributeArray/setUniformValueArray do not take arrays
- 931 isinstance() fails with Signal instances
- 928 100's of QGraphicItems with signal connections causes slowdown
- 930 Documentation mixes signals and functions.
- 923 Make QScriptValue (or QScriptValueIterator) implement the Python iterator protocol
- 922 QScriptValue's repr() should give some information about its data
- 900 QtCore.Property as decorator
- 895 jQuery version is outdated, distribution code de-duplication breaks documentation search
- 731 Can't specify more than a single 'since' argument
- 983 copy.deepcopy raises SystemError with QColor
- 947 NETWORK_ERR during interaction QtWebKit window with server
- 873 Deprecated methods could emit DeprecationWarning
- 831 PySide docs would have a "Inherited by" list for each class
1.0.5 (2011-07-22)
------------------
Major changes
~~~~~~~~~~~~~
- Widgets present on "ui" files are exported in the root widget, check PySide ML thread for more information[1];
- pyside-uic generate menubars without parent on MacOS plataform;
- Signal connection optimizations;
Bug fixes
~~~~~~~~~
- 892 Segfault when destructing QWidget and QApplication has event filter installed
- 407 Crash while multiple inheriting with QObject and native python class
- 939 Shiboken::importModule must verify if PyImport_ImportModule succeeds
- 937 missing pid method in QProcess
- 927 Segfault on QThread code.
- 925 Segfault when passing a QScriptValue as QObject or when using .toVariant() on a QScriptValue
- 905 QtGui.QHBoxLayout.setMargin function call is created by pyside-uic, but this is not available in the pyside bindings
- 904 Repeatedly opening a QDialog with Qt.WA_DeleteOnClose set crashes PySide
- 899 Segfault with 'QVariantList' Property.
- 893 Shiboken leak reference in the parent control
- 878 Shiboken may generate incompatible modules if a new class is added.
- 938 QTemporaryFile JPEG problem
- 934 A __getitem__ of QByteArray behaves strange
- 929 pkg-config files do not know about Python version tags
- 926 qmlRegisterType does not work with QObject
- 924 Allow QScriptValue to be accessed via []
- 921 Signals not automatically disconnected on object destruction
- 920 Cannot use same slot for two signals
- 919 Default arguments on QStyle methods not working
- 915 QDeclarativeView.scene().addItem(x) make the x object invalid
- 913 Widgets inside QTabWidget are not exported as members of the containing widget
- 910 installEventFilter() increments reference count on target object
- 907 pyside-uic adds MainWindow.setMenuBar(self.menubar) to the generated code under OS X
- 903 eventFilter in ItemDelegate
- 897 QObject.property() and QObject.setProperty() methods fails for user-defined properties
- 896 QObject.staticMetaObject() is missing
- 916 Missing info about when is possible to use keyword arguments in docs [was: QListWidgetItem's constructor ignores text parameter]
- 890 Add signal connection example for valueChanged(int) on QSpinBox to the docs
- 821 Mapping interface for QPixmapCache
- 909 Deletion of QMainWindow/QApplication leads to segmentation fault
dist/changes-5.12.1 0000664 0000000 0000000 00000004443 13766170131 0014110 0 ustar 00root root 0000000 0000000 Qt for Python 5.12.1 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-878] Added binding for QWebEngineUrlScheme which was missing
- Completed the signature introspection
- Activated existence_test.py for 5.12
- [PYSIDE-868] Fixed a crash related to multiple inheritance
- [PYSIDE-886] Fixed crash when mixing static overloads with instance methods in derived classes
- [PYSIDE-892] Added free functions from namespace QtQml
- Fixed a rare type hint racing condition
- Used helper function for accessing the meta object in quick type registration for libpyside
- [PYSIDE-883] Fixed regression related to removing createIndex method that uses PyObject*
- [PYSIDE-882] Avoided the creation of empty build directories in the install tree
- Produced TypeError messages using the signature module
- Replaced nullptr by None in signatures in the documentation
- Updated and fixed the Slot documentation
- Added \nullptr macro definition in the documentation
- [PYSIDE-874] Fixed wrong METADATA for generated wheels
- [PYSIDE-898] Improved check when a QFlag is found
- [PYSIDE-790] Fixed a crash when overriding QAbstractNativeEventFilter.QAbstractNativeEventFilter()
- Added support for the help() function using the signature module
- [PYSIDE-880] Fixed an issue on the setup.py when running under non-UTF8 locale
****************************************************************************
* Shiboken2 *
****************************************************************************
- Make signatures in overload decisor code more verbose in shiboken
- [PYSIDE-914] Included MSVC dlls in the shiboken module package
dist/changes-5.12.2 0000664 0000000 0000000 00000005073 13766170131 0014111 0 ustar 00root root 0000000 0000000 Qt for Python 5.12.2 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-934] Added a method to VoidPtr called toBytes() to get the bytes representation.
- [PYSIDE-95] Added ownership transfer for QGraphicsItemGroup.addToGroup
- [PYSIDE-928][PYSIDE-937][PYSIDE-943] Fixing a refcounting bug shown by __doc__ handling
- [PYSIDE-931] Added the attribute 'allow-thread' to the type system and class entries.
- [PYSIDE-947] Fixed conversions of list of smart pointers to python
- [PYSIDE-953] Preventing Python 3.5 from crashing the build
- [PYSIDE-940] Added setPageSize new signature to QPageSize
- [PYSIDE-950] Allowed subclassing PyCFunction in extension modules
- [PYSIDE-938] Set the proper parent when overloading QUiLoader.addAction()
- Added common QPrintSupport typesystem for QWebEngine
- [PYSIDE-942] Fixed an error when importing signatures in frozen executables
- [PYSIDE-948] Fixed problem when using smart pointers with namespaces
- [PYSIDE-45] Added support for using PyObject wrapper when an invalid QVariant is used
- [PYSIDE-922] Added pyObj check for the setSequenceOwnership
- [PYSIDE-919] Modernized the cmake build process
- [PYSIDE-924] Propagated Property attributes to the MetaObject
- Improved the type hints for containers
- [PYSIDE-906] Added missing classes QWebEngineHistory and WebEngineHistoryItem
- Added QtRemoteObject classes
- Added a script to generate a debug log in windows called debug_windows.py
****************************************************************************
* Shiboken2 *
****************************************************************************
- Fixed many build warnings on shiboken and pyside
- Extended the exception handling test in shiboken
- [PYSIDE-929] Added dependency version for shiboken2
- [PYSIDE-914] Including MSVC dlls in the shiboken module package
- [PYSIDE-932] Implement Embedding To Make Signatures Always Available
dist/changes-5.12.3 0000664 0000000 0000000 00000003242 13766170131 0014106 0 ustar 00root root 0000000 0000000 Qt for Python 5.12.3 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-993] Use correct environment variable to detect when running in Coin
- Many updated to the documentation
- Add array modification for QGLShaderProgram::setAttributeArray(int,const float *v,int,int)
- Signatures: Add support for PySide2.QtCore.short/ushort/signed char
- Add explicit methods for QOpenGLShaderProgramm.setUniformValue (i/f)
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-977] Shiboken: Add "noexcept" to wrapper when wrapped function is noexcept
- [PYSIDE-975] shiboken: Allow for include paths with relative directories
- [PYSIDE-995] shiboken: Enable adding call operators
- shiboken: Move the Api extractor documentation into shiboken
- shiboken: Fix code injection not working for operator functions
- shiboken: Enable including typesystem XML snippets via entities
dist/changes-5.12.4 0000664 0000000 0000000 00000004274 13766170131 0014115 0 ustar 00root root 0000000 0000000 Qt for Python 5.12.4 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-571] correct bool(qApp) on Python 2
- [PYSIDE-735] generate_pyi: Simplify, Enhance and Get Rid Of Any Import Problems
- [PYSIDE-865] opengl/contextinfo.py: Fix exception on exit
- [PYSIDE-865] opengl/contextinfo.py: Polish the example a bit
- [PYSIDE-908] Complete the help() support for Types
- [PYSIDE-955] Add PySide2: Add OpenGL version functions as separate module
- [PYSIDE-980] CMake: Change the default behavior CMAKE_BUILD_TYPE
- [PYSIDE-996] Fix PyInstaller after removal of COIN glitches
- [PYSIDE-1003] Fix Shiboken.ObjectType.__new__ for Python 2.7 V2
- [PYSIDE-1004] Make the __signature__ attribute writable by default
- [PYSIDE-1008] Fix propagation of existing LD env vars when calling generate_pyi
- [PYSIDE-1009] Signature: Try to recognize unknown modules in errorhandler.py
- [PYSIDE-1012] Fix build on centOS/conda forge
- [PYSIDE-1019] PySide: Allow any existing attribute in the constructor
- [PYSIDE-1022] TabbedBrowser Example: Fix "Open in new tab"
- [PYSIDE-1027] Fix negative refcount on QSocketNotifier
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-955] shiboken/Generators: Cache class information lists per class
- [PYSIDE-1016] shiboken: Fix handling shared pointers passed by const-ref, take 2
- [PYSIDE-1017] shiboken: Enable specifying names for a parameters of added functions
dist/changes-5.12.5 0000664 0000000 0000000 00000003342 13766170131 0014111 0 ustar 00root root 0000000 0000000
Qt for Python 5.12.5 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-571] Support the qApp macro in "scriptable application"
- [PYSIDE-634] Add support for parameterNames in Signals
- [PYSIDE-951] Correct QtPrintSupport dependency
- [PYSIDE-1010] Add optional support for types in QSettings::value
- [PYSIDE-1020] Fix pyside2-uic to generate correct code for QWebview and QQuickWidget
- [PYSIDE-1028] Leave QVariantMap as a name, not a type
- [PYSIDE-1029] Fix type name for lookup of QFlags<> converters
- [PYSIDE-1032] Use default compiler on macOS
- [PYSIDE-1035] Fix pyside2-uic to generate correct code for QTableWidget
- [PYSIDE-1066] Fix Xcode sdk value embedded into PySide2 binaries
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1024] shiboken: Generate code for smart pointers only within declaring package
- [PYSIDE-1037] shiboken: Allow for "auto" as target of type for CONVERTTOCPP in injected code
dist/changes-5.12.6 0000664 0000000 0000000 00000002113 13766170131 0014105 0 ustar 00root root 0000000 0000000 Qt for Python 5.12.6 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [Fixes: PYSIDE-1007] Remove extra ref on QDataStream::setDevice
- [Fixes: PYSIDE-1051] Fix heaptype conflict with QtCore.QObject.__new__in Python 2.7
****************************************************************************
* Shiboken2 *
****************************************************************************
- No changes
dist/changes-5.13.0 0000664 0000000 0000000 00000002611 13766170131 0014103 0 ustar 00root root 0000000 0000000 Qt for Python 5.13.0 is a minor release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-487] Add bindings for 5.13
- [PYSIDE-571] Support the qApp macro in "scriptable application"
- [PYSIDE-841] Doc: Add QML Integration tutorial
- [PYSIDE-841] Docs: Add Expenses tool tutorial
- [PYSIDE-855] Regenerate all example forms using the python-extended rcc of 5.14
- [PYSIDE-1029] Fix type name for lookup of QFlags<> converters
- [PYSIDE-1032] Use default compiler on macOS
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1024] shiboken: Generate code for smart pointers only within declaring package
dist/changes-5.13.1 0000664 0000000 0000000 00000004312 13766170131 0014104 0 ustar 00root root 0000000 0000000
Qt for Python 5.13.1 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [Fixes https://github.com/spyder-ide/qtpy/issues/195] Fix RuntimeError: dictionary changed size during iteration
- [PYSIDE-634] Add support for parameterNames in Signals
- [PYSIDE-951] Cleanup signature module before substantial change
- [PYSIDE-951] correct QtPrintSupport dependency
- [PYSIDE-1010] Add optional support for types in QSettings::value
- [PYSIDE-1020] Fix pyside2-uic to generate correct code for QWebview and QQuickWidget
- [PYSIDE-1028] Leave QVariantMap as a name, not a type
- [PYSIDE-1033] CMake modularization: macros creation
- [PYSIDE-1035] Fix pyside2-uic to generate correct code for QTableWidget
- [PYSIDE-1051] Fix heaptype conflict with QtCore.QObject.__new__in Python 2.7
- [PYSIDE-1052] Add QtCore.Slot.__signature__ and much more manually
- [PYSIDE-1059] Documentation: update QInputDialog snippets
- [PYSIDE-1066] Fix Xcode sdk value embedded into PySide2 binaries
- [PYSIDE-1067] Update docs style
- [PYSIDE-1073] Fix a typing bug in Python 2.7 and update
- [PYSIDE-1077] Fix wrong Python init return codes
- [PYSIDE-1079] signature: Support typing.Optional[T] and refine a bit
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1024] shiboken: Generate code for smart pointers only within declaring package
- [PYSIDE-1037] shiboken: Allow for "auto" as target of type for CONVERTTOCPP in injected code
dist/changes-5.13.2 0000664 0000000 0000000 00000003074 13766170131 0014111 0 ustar 00root root 0000000 0000000 Qt for Python 5.13.2 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-785] Release ownership in QAbstractVideoFilterWrapper::createFilterRunnable
- [PYSIDE-820] Fix booleans and empty list cases in QSettings
- [PYSIDE-849] Add inject-code for QVideoFrame::bits()
- [PYSIDE-1007] Remove extra ref on QDataStream::setDevice
- [PYSIDE-1019] libpyside: Fix compiler warning
- [PYSIDE-1049] Split build instructions to build and packaging
- [PYSIDE-1051] Fix heaptype conflict with QtCore.QObject.__new__in Python 2.7
- [PYSIDE-1089] Fix formatting of the deployment documentation
- [PYSIDE-1093] Fix bad shutdown effect on QApplication.instance()
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1095] shiboken: Fix handling of modified default expressions
dist/changes-5.14.0 0000664 0000000 0000000 00000006635 13766170131 0014116 0 ustar 00root root 0000000 0000000 Qt for Python 5.14.0 is a minor release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important Source Incompatible/Behavior Changes *
****************************************************************************
- [PYSIDE-990] It is no longer possible to nest types in typesystem files by
by qualifying the namespace components with "::". The elements
need to be properly nested.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-487] Add bindings for Qt 5.14
- [PYSIDE-785] Release ownership in QAbstractVideoFilterWrapper::createFilterRunnable
- [PYSIDE-795] Create a framework for deprecated functions
- [PYSIDE-795] Make the function registry more usable in Python modules
- [PYSIDE-795] Improve the NumPy Support by iterables
- [PYSIDE-820] Fix booleans and empty list cases in QSettings
- [PYSIDE-849] Add inject-code for QVideoFrame::bits()
- [PYSIDE-939] Add support for Python 3.8
- [PYSIDE-939] Fix refcount issues with QSettings glue code
- [PYSIDE-939] Finalize the Python 3.8 refcount fix
- [PYSIDE-951] Support Pointer Primitive Types by Arrays or Result Tuples
- [PYSIDE-1007] Remove extra ref on QDataStream::setDevice
- [PYSIDE-1033] CMake modularization: macros creation
- [PYSIDE-1041] Enable multimedia classes after API fixup
- [PYSIDE-1047] QtWinExtras: Add QtWin namespace
- [PYSIDE-1051] Fix heaptype conflict with QtCore.QObject.__new__in Python 2.7
- [PYSIDE-1052] Add QtCore.Slot.__signature__ and much more manually
- [PYSIDE-1059] Documentation: update QInputDialog snippets
- [PYSIDE-1066] Fix Xcode sdk value embedded into PySide2 binaries
- [PYSIDE-1067] Update docs style
- [PYSIDE-1067] New documentation structure
- [PYSIDE-1068] Add designer to the pyside tools
- [PYSIDE-1073] Fix a typing bug in Python 2.7 and update
- [PYSIDE-1077] Fix wrong Python init return codes
- [PYSIDE-1079] signature: Support typing.Optional[T] and refine a bit
- [PYSIDE-1089] Fix formatting of the deployment documentation
- [PYSIDE-1093] Fix bad shutdown effect on QApplication.instance()
- [PYSIDE-1098] Replace pyside2-uic/pyside2-rcc by
uic/rcc which now have an option to generate Python
- [PYSIDE-1101] Remove QGraphicsItem::scroll from QtChart
- [PYSIDE-1140] Add python_requires to the python setup
- [QTBUG-66304] Blacklist failing QtPositioning test
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-454] Fix crash when smartptr template class cannot be found
- [PYSIDE-1037] Allow for "auto" as target of type for CONVERTTOCPP in injected code
- [PYSIDE-1095] Fix handling of modified default expressions
dist/changes-5.14.1 0000664 0000000 0000000 00000003076 13766170131 0014113 0 ustar 00root root 0000000 0000000 Qt for Python 5.14.1 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-841] Add example for Threads and Signals
- [PYSIDE-1135] qApp: Ensure QtCore import when embedded QApplication subclass is used
- [PYSIDE-1158] Let qApp be noApp instead of pretending to be None
- [PYSIDE-1164] qApp: make sure to create the right instance when embedding
- [PYSIDE-1165] designer: patch rpath for unix
- [PYSIDE-1192] libpyside: Set default signal name only if previously assigned
- [PYSIDE-1201] docs: Fix pre overlap and improve reading
- [PYSIDE-1205] libpyside: avoid freeing char*
- [PYSIDE-1207] Fix ownership of QTextDocument::createObject
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1191] shiboken: Introduce "until" version attribute as opposite of "since"
dist/changes-5.14.2 0000664 0000000 0000000 00000006733 13766170131 0014117 0 ustar 00root root 0000000 0000000 Qt for Python 5.14.2 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-135] Add doc getter for Property
- [PYSIDE-239] Python enum types can now be used as a valid signal type.
- [PYSIDE-939] Fix Python 3.8 warnings about deprecated int conversions of
enums/flags
- [PYSIDE-571] qApp has been turned into a normal Python variable. This
implies that QtWidgets.qApp no longer works;
it should be replaced by qApp.
- [PYSIDE-803] GUI slowdowns caused by background threads have been fixed by
reducing GIL allocation and usage of
Py_(BEGIN|END)_ALLOW_THREADS.
- [PYSIDE-858] Windows binaries are now signed.
- [PYSIDE-939] Fix testrunner for Python 3.8/Linux
- [PYSIDE-946] Add functions with callback of QWebEnginePage
- [PYSIDE-1231] Further issues introduced by Python 3.8 have been addressed:
- Warnings about deprecated int conversions of enumerations
and flags have been fixed.
- Packages can now be built with Python 3.8.1.
- Tests run with Python 3.8.1.
- [PYSIDE-1189] A crash caused by wrong ownership of the return value of
QList/QTable/QTreeWidget.mimeData() has been fixed.
- [PYSIDE-1199] The webchannel standalone example has been added.
- [PYSIDE-1204] QByteArray now properly supports the PyBuffer interface.
- [PYSIDE-1214] For accessors returning non-exposed classes inheriting
QObject, the most-derived wrapper is now created.
- [PYSIDE-1229] testrunner: Fix disrupted lines in the error log
- [PYSIDE-1236] Fix running scriptableapplication in a virtualenv on Windows
with Python 3.8
- [PYSIDE-1247] Avoid a signature warning in Python 3.6
- [PYSIDE-1250] PySide2: Use int for QVariant conversion when possible
- [PYSIDE-1251] Invert QTreeWidgetItem clear function loop
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-803] The default of the "allow-thread" attribute has been changed
to false as it was observed to cause performance issues when
using threads.
- [PYSIDE-1112] The shiboken documentation has been re-structured.
- [PYSIDE-1228] Typedef'ed anonymous enums are now supported.
- [PYSIDE-1240] The manual test dumpcodemodel has been modified to output
typesystem XML, enabling convenient generation of typesystem
file skeletons for new bindings.
- [PYSIDE-1241] Improve error messages about invalid types of added functions
- [PYSIDE-1241] Enable flags types in added functions
- [PYSIDE-1246] Fix classes with virtual destructors not being considered
polymorphic
dist/changes-5.14.2.2 0000664 0000000 0000000 00000003346 13766170131 0014254 0 ustar 00root root 0000000 0000000 Qt for Python 5.14.2.2 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-1100] Support type checking with the mypy module
- [PYSIDE-1236] samplebinding: Fix running with Python 3.8.2 on Windows
- [PYSIDE-1255] Fix memory corruption for QML registered types
- [PYSIDE-1271] QMutexLocker: allow-thread in constructor
- [PYSIDE-1272] signature: Add comparison for existing_doc type
- [PYSIDE-1285] qareaseries: keep references of lower/upper series
- [PYSIDE-1293] Windows: Fix encoding in custom message handler
- [PYSIDE-15] Support pickling of Qt Enum objects
- [PYSIDE-1223] Add QtUiTools.loadUiType
- [PYSIDE-1286] Implement __qualname__ and correct __module__ for classes
- [PYSIDE-1303] PySide2: Fix conversion of quintptr
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1286] shiboken: Prepare for introduction of __qualname__
- [PYSIDE-1298] libshiboken: Support musl libc
- [PYSIDE-1299] shiboken: Fix cross builds
dist/changes-5.14.2.3 0000664 0000000 0000000 00000002767 13766170131 0014263 0 ustar 00root root 0000000 0000000 Qt for Python 5.14.2.3 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-1223] pyside2-uic instead of uic is not used for loadUiType()
- [PYSIDE-1257] Deployment with cx_freeze using zip_include_packages has
been fixed
- [PYSIDE-1282] A crash using QThread.terminate() on pthreads has
been fixed
- [PYSIDE-1311] The downloads functionality of the Tabbedbrowser example
has been fixed
- [PYSIDE-1321] A leaking reference in the PySide2 property getter has
been fixed
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-1325] Wrong generated code for default-initialized function
arguments ({}) has been fixed
dist/changes-5.15.0 0000664 0000000 0000000 00000004455 13766170131 0014115 0 ustar 00root root 0000000 0000000 Qt for Python 5.15.0 is a minor release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-487] Add API of Qt 5.15
- [PYSIDE-487] Add support for QSerialPort
- [PYSIDE-487] Add QtQuickControls2
- [PYSIDE-841] example: add systray example
- [PYSIDE-841] doc: add more videos from Qt events
- [PYSIDE-841] doc: add tutorial for using qrc files
- [PYSIDE-904] libpyside: Remove deprecated API
- [PYSIDE-904] Add support for template type aliases
- [PYSIDE-957] Add a tool to dump meta objects of QObject-derived classes
- [PYSIDE-1280] Enable injecting raw code for setattro/getattro
- [PYSIDE-1309] Rename and update some snippets
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-454] shiboken: Add a way of specifying system includes to be parsed
- [PYSIDE-454] shiboken: Handle smart pointers with const pointees
- [PYSIDE-904] libshiboken: Remove deprecated API
- [PYSIDE-957] shiboken: Fix refcounts of sbkenum
- [PYSIDE-990] shiboken: Handle inline namespaces
- [PYSIDE-1024] shiboken: Make it possible to specify smartpointer instantiations
- [PYSIDE-1074] shiboken: Fix classes in hidden namespaces
- [PYSIDE-1188] shiboken: Fix shared pointer return value in virtual function
- [PYSIDE-1265] shiboken: Introduce a separate logging category for documentation generation
- [PYSIDE-1265] shiboken: Change debug messages to use qCInfo and remove some messages
- [PYSIDE-1267] shiboken: Allow for parsing headers under system include paths
- [PYSIDE-1296] shiboken: Support non-type template parameters in functions
dist/changes-5.15.1 0000664 0000000 0000000 00000007046 13766170131 0014115 0 ustar 00root root 0000000 0000000 Qt for Python 5.15.1 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-74] Implement default __ne__ and __eq__ for all PySide types
- [PYSIDE-198] Add compatibility with Nuitka
- [PYSIDE-829] signature: Avoid non-existent attributes in compiled code (Nuitka)
- [PYSIDE-841] doc: Add widget styling tutorial
- [PYSIDE-841] add quick painteditem example
- [PYSIDE-904] Add QObject.findChildren(QRegularExpression)
- [PYSIDE-904] qp5_tool.py: Add an configuration key for the CMake generator
- [PYSIDE-904] Port some examples from QRegExp to QRegularExpression
- [PYSIDE-904] Fix libsample/photon test for Qt 6 / Windows
- [PYSIDE-904] Enable adding operators ==, != as functions without code injection
- [PYSIDE-957] Implement the QEnum/QFlag decorator, V2
- [PYSIDE-981] Return QVariantList when using list as Signal argument
- [PYSIDE-1019] feature-select: Implement a selectable feature framework
- [PYSIDE-1019] feature-select: allow snake_case instead of camelCase for methods
- [PYSIDE-1019] feature-select: delay the feature switching
- [PYSIDE-1223] Use pyside2-uic instead of uic for the loadUiType
- [PYSIDE-1257] Potential fix for deploying with cx_freeze using zip_include_packages
- [PYSIDE-1282] pthreads: Try to abandon the GIL in case a thread was terminated
- [PYSIDE-1292] Doc: Enable doc builds using the offline template
- [PYSIDE-1313] basewrapper.cpp: add PyErr_Fetch/Restore in SbkDeallocWrapperCommon()
- [PYSIDE-1317] Add QSocketDescriptor class
- [PYSIDE-1321] Fix leaking reference in PySide2 property getter
- [PYSIDE-1321] Fix some leaks in enumeration creation
- [PYSIDE-1323] Add missing Win runtime dll into win wheels
- [PYSIDE-1323] Update vcredist binaries for MSVC 2019
- [PYSIDE-1332] Fix crashes in QThread::wait(), QWaitCondition::wait()
- [PYSIDE-1349] QQmlComponent: allow thread in constructors
- [PYSIDE-1353] doc: fix Property indentation
- [PYSIDE-1355] Add Qt3DExtras.QNormalDiffuseMapAlphaMaterial
- [PYSIDE-1368] __feature__: ignore if `__name__` does not exist in a module
- [PYSIDE-1372] QDomElement: remove unnecesary setAttribute overloads
- [PYSIDE-1374] Add the QWidget *-based overloads of the QtWinExtras functions
****************************************************************************
* Shiboken2 *
****************************************************************************
* shiboken now accepts multiple headers on the command line.
* A number of error and warning messages have been prefixed by file name
and line for better tooling.
- [PYSIDE-841] Add custom widget shiboken example
- [PYSIDE-904] shiboken2: Handle virtual methods returning a reference
- [PYSIDE-1019] shiboken2: Re-add support for parsing Q_PROPERTY
- [PYSIDE-1177] shiboken: Fix __doc__ setter for derived types
- [PYSIDE-1325] shiboken: Fix default-initialized function arguments
- [PYSIDE-1327] shiboken: Resolve typedef'ed base classes
dist/changes-5.15.2 0000664 0000000 0000000 00000006741 13766170131 0014117 0 ustar 00root root 0000000 0000000 Qt for Python 5.15.2 is a bug-fix release.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qtforpython/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important Source Incompatible/Behavior Changes *
****************************************************************************
- Projects generating bindings for Qt-based code no longer need to include
pyside2_global.h for the property and signal/slot annotations to work.
****************************************************************************
* PySide2 *
****************************************************************************
- [PYSIDE-487] Some missing enumerations and classes were added.
- [PYSIDE-644] QNetworkCookie was added to WebEngineCore.
- [PYSIDE-665] A crash when reimplementing QLayout.takeAt() was fixed.
- [PYSIDE-807] setup.py was rewritten to properly show options the in command
help.
- [PYSIDE-972] Launching PySide2 from paths with non-ASCII Latin1 characters
was fixed.
- [PYSIDE-1019] feature_select: Qt Properties are now represented as Python
properties.
- [PYSIDE-1070] A crash when overriding QUiLoader::createWidget() in QUiLoader
was fixed.
- [PYSIDE-1082] A crash when creating QMimeData from
Q(Plain)TextEdit::createMimeDataFromSelection() was fixed.
- [PYSIDE-1202] More classes from QtConcurrent were added.
- [PYSIDE-1224] The namespace QColorConstants was added.
- [PYSIDE-1326] Operators for QFlags on hidden top level namespace are now
generated.
- [PYSIDE-1354] Slots being invoked from the wrong thread were fixed.
- [PYSIDE-1381] The dependency of the QtQml module header on internal header
pysideqmlregistertype.h was removed.
- [PYSIDE-1385] Deprecated wheel.pep425tags imports were removed.
- [PYSIDE-1390] setup.py: The build_rst_docs command was added to build
rst documentation only
- [PYSIDE-1397] Functions taking a smart pointer now accept smart pointers to
base classes.
- [PYSIDE-1410] QAxBase::dynamicCall() was fixed.
****************************************************************************
* Shiboken2 *
****************************************************************************
- [PYSIDE-841] The documentation on modifications was restructured.
- [PYSIDE-904] An attribute for generating "using namespace" was added.
- [PYSIDE-1019] A way of specifying properties for non-Qt classes in
typesystem XML was added.
- [PYSIDE-1075] Functions from invisible namespaces are now generated into
their parent namespaces.
- [PYSIDE-1224] Variables in namespaces are now generated.
- [PYSIDE-1366] The order of overloads may now be specified to work around
problems with the order generated by the overload decisor.
- [PYSIDE-1388] Final classes with protected methods when disabling the
protected hack are now correctly generated.
docs/ 0000775 0000000 0000000 00000000000 13766170131 0012013 5 ustar 00root root 0000000 0000000 docs/.gitignore 0000664 0000000 0000000 00000000010 13766170131 0013772 0 ustar 00root root 0000000 0000000 _build/
examples/ 0000775 0000000 0000000 00000000000 13766170131 0012701 5 ustar 00root root 0000000 0000000 examples/3d/ 0000775 0000000 0000000 00000000000 13766170131 0013207 5 ustar 00root root 0000000 0000000 examples/3d/3d.pyproject 0000664 0000000 0000000 00000000041 13766170131 0015451 0 ustar 00root root 0000000 0000000 {
"files": ["simple3d.py"]
}
examples/3d/simple3d.py 0000664 0000000 0000000 00000014141 13766170131 0015302 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the qt3d/simple-cpp example from Qt v5.x"""
import sys
from PySide2.QtCore import(Property, QObject, QPropertyAnimation, Signal)
from PySide2.QtGui import (QGuiApplication, QMatrix4x4, QQuaternion, QVector3D)
from PySide2.Qt3DCore import (Qt3DCore)
from PySide2.Qt3DExtras import (Qt3DExtras)
class OrbitTransformController(QObject):
def __init__(self, parent):
super(OrbitTransformController, self).__init__(parent)
self._target = None
self._matrix = QMatrix4x4()
self._radius = 1
self._angle = 0
def setTarget(self, t):
self._target = t
def getTarget(self):
return self._target
def setRadius(self, radius):
if self._radius != radius:
self._radius = radius
self.updateMatrix()
self.radiusChanged.emit()
def getRadius(self):
return self._radius
def setAngle(self, angle):
if self._angle != angle:
self._angle = angle
self.updateMatrix()
self.angleChanged.emit()
def getAngle(self):
return self._angle
def updateMatrix(self):
self._matrix.setToIdentity()
self._matrix.rotate(self._angle, QVector3D(0, 1, 0))
self._matrix.translate(self._radius, 0, 0)
if self._target is not None:
self._target.setMatrix(self._matrix)
angleChanged = Signal()
radiusChanged = Signal()
angle = Property(float, getAngle, setAngle, notify=angleChanged)
radius = Property(float, getRadius, setRadius, notify=radiusChanged)
class Window(Qt3DExtras.Qt3DWindow):
def __init__(self):
super(Window, self).__init__()
# Camera
self.camera().lens().setPerspectiveProjection(45, 16 / 9, 0.1, 1000)
self.camera().setPosition(QVector3D(0, 0, 40))
self.camera().setViewCenter(QVector3D(0, 0, 0))
# For camera controls
self.createScene()
self.camController = Qt3DExtras.QOrbitCameraController(self.rootEntity)
self.camController.setLinearSpeed(50)
self.camController.setLookSpeed(180)
self.camController.setCamera(self.camera())
self.setRootEntity(self.rootEntity)
def createScene(self):
# Root entity
self.rootEntity = Qt3DCore.QEntity()
# Material
self.material = Qt3DExtras.QPhongMaterial(self.rootEntity)
# Torus
self.torusEntity = Qt3DCore.QEntity(self.rootEntity)
self.torusMesh = Qt3DExtras.QTorusMesh()
self.torusMesh.setRadius(5)
self.torusMesh.setMinorRadius(1)
self.torusMesh.setRings(100)
self.torusMesh.setSlices(20)
self.torusTransform = Qt3DCore.QTransform()
self.torusTransform.setScale3D(QVector3D(1.5, 1, 0.5))
self.torusTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1, 0, 0), 45))
self.torusEntity.addComponent(self.torusMesh)
self.torusEntity.addComponent(self.torusTransform)
self.torusEntity.addComponent(self.material)
# Sphere
self.sphereEntity = Qt3DCore.QEntity(self.rootEntity)
self.sphereMesh = Qt3DExtras.QSphereMesh()
self.sphereMesh.setRadius(3)
self.sphereTransform = Qt3DCore.QTransform()
self.controller = OrbitTransformController(self.sphereTransform)
self.controller.setTarget(self.sphereTransform)
self.controller.setRadius(20)
self.sphereRotateTransformAnimation = QPropertyAnimation(self.sphereTransform)
self.sphereRotateTransformAnimation.setTargetObject(self.controller)
self.sphereRotateTransformAnimation.setPropertyName(b"angle")
self.sphereRotateTransformAnimation.setStartValue(0)
self.sphereRotateTransformAnimation.setEndValue(360)
self.sphereRotateTransformAnimation.setDuration(10000)
self.sphereRotateTransformAnimation.setLoopCount(-1)
self.sphereRotateTransformAnimation.start()
self.sphereEntity.addComponent(self.sphereMesh)
self.sphereEntity.addComponent(self.sphereTransform)
self.sphereEntity.addComponent(self.material)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = Window()
view.show()
sys.exit(app.exec_())
examples/axcontainer/ 0000775 0000000 0000000 00000000000 13766170131 0015214 5 ustar 00root root 0000000 0000000 examples/axcontainer/axcontainer.pyproject 0000664 0000000 0000000 00000000041 13766170131 0021463 0 ustar 00root root 0000000 0000000 {
"files": ["axviewer.py"]
}
examples/axcontainer/axviewer.py 0000664 0000000 0000000 00000006641 13766170131 0017427 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 Active Qt Viewer example"""
import sys
from PySide2.QtAxContainer import QAxSelect, QAxWidget
from PySide2.QtWidgets import (QAction, QApplication, QDialog,
QMainWindow, QMessageBox, QToolBar)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
toolBar = QToolBar()
self.addToolBar(toolBar)
fileMenu = self.menuBar().addMenu("&File")
loadAction = QAction("Load...", self, shortcut="Ctrl+L", triggered=self.load)
fileMenu.addAction(loadAction)
toolBar.addAction(loadAction)
exitAction = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close)
fileMenu.addAction(exitAction)
aboutMenu = self.menuBar().addMenu("&About")
aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
aboutMenu.addAction(aboutQtAct)
self.axWidget = QAxWidget()
self.setCentralWidget(self.axWidget)
def load(self):
axSelect = QAxSelect(self)
if axSelect.exec_() == QDialog.Accepted:
clsid = axSelect.clsid()
if not self.axWidget.setControl(clsid):
QMessageBox.warning(self, "AxViewer", "Unable to load " + clsid + ".")
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
availableGeometry = app.desktop().availableGeometry(mainWin)
mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
mainWin.show()
sys.exit(app.exec_())
examples/charts/ 0000775 0000000 0000000 00000000000 13766170131 0014165 5 ustar 00root root 0000000 0000000 examples/charts/audio.py 0000664 0000000 0000000 00000011620 13766170131 0015640 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the charts/audio example from Qt v5.x"""
import sys
from PySide2.QtCharts import QtCharts
from PySide2.QtCore import QPointF
from PySide2.QtMultimedia import (QAudioDeviceInfo, QAudioFormat,
QAudioInput)
from PySide2.QtWidgets import QApplication, QMainWindow, QMessageBox
sampleCount = 2000
resolution = 4
class MainWindow(QMainWindow):
def __init__(self, device):
super(MainWindow, self).__init__()
self.series = QtCharts.QLineSeries()
self.chart = QtCharts.QChart()
self.chart.addSeries(self.series)
self.axisX = QtCharts.QValueAxis()
self.axisX.setRange(0, sampleCount)
self.axisX.setLabelFormat("%g")
self.axisX.setTitleText("Samples")
self.axisY = QtCharts.QValueAxis()
self.axisY.setRange(-1, 1)
self.axisY.setTitleText("Audio level")
self.chart.setAxisX(self.axisX, self.series)
self.chart.setAxisY(self.axisY, self.series)
self.chart.legend().hide()
self.chart.setTitle("Data from the microphone ({})".format(device.deviceName()))
formatAudio = QAudioFormat()
formatAudio.setSampleRate(8000)
formatAudio.setChannelCount(1)
formatAudio.setSampleSize(8)
formatAudio.setCodec("audio/pcm")
formatAudio.setByteOrder(QAudioFormat.LittleEndian)
formatAudio.setSampleType(QAudioFormat.UnSignedInt)
self.audioInput = QAudioInput(device, formatAudio, self)
self.ioDevice = self.audioInput.start()
self.ioDevice.readyRead.connect(self._readyRead)
self.chartView = QtCharts.QChartView(self.chart)
self.setCentralWidget(self.chartView)
self.buffer = [QPointF(x, 0) for x in range(sampleCount)]
self.series.append(self.buffer)
def closeEvent(self, event):
if self.audioInput is not None:
self.audioInput.stop()
event.accept()
def _readyRead(self):
data = self.ioDevice.readAll()
availableSamples = data.size() // resolution
start = 0
if (availableSamples < sampleCount):
start = sampleCount - availableSamples
for s in range(start):
self.buffer[s].setY(self.buffer[s + availableSamples].y())
dataIndex = 0
for s in range(start, sampleCount):
value = (ord(data[dataIndex]) - 128) / 128
self.buffer[s].setY(value)
dataIndex = dataIndex + resolution
self.series.replace(self.buffer)
if __name__ == '__main__':
app = QApplication(sys.argv)
inputDevice = QAudioDeviceInfo.defaultInputDevice()
if (inputDevice.isNull()):
QMessageBox.warning(None, "audio", "There is no audio input device available.")
sys.exit(-1)
mainWin = MainWindow(inputDevice)
mainWin.setWindowTitle("audio")
availableGeometry = app.desktop().availableGeometry(mainWin)
size = availableGeometry.height() * 3 / 4
mainWin.resize(size, size)
mainWin.show()
sys.exit(app.exec_())
examples/charts/callout.py 0000664 0000000 0000000 00000023242 13766170131 0016205 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Callout example from Qt v5.x"""
import sys
from PySide2.QtWidgets import (QApplication, 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) and not self._anchor.isNull():
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(True)
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_())
examples/charts/charts.pyproject 0000664 0000000 0000000 00000000421 13766170131 0017407 0 ustar 00root root 0000000 0000000 {
"files": ["percentbarchart.py", "donutbreakdown.py", "legend.py", "nesteddonuts.py",
"modeldata.py", "lineandbar.py", "memoryusage.py", "callout.py", "audio.py",
"linechart.py", "logvalueaxis.py", "piechart.py", "temperaturerecords.py"]
}
examples/charts/chartthemes/ 0000775 0000000 0000000 00000000000 13766170131 0016474 5 ustar 00root root 0000000 0000000 examples/charts/chartthemes/README.md 0000664 0000000 0000000 00000000361 13766170131 0017753 0 ustar 00root root 0000000 0000000 # Chart themes
To generated the file `ui_themewidget.py`, the following
command need to be executed:
`pyside2-uic themewidget.ui > ui_themewidget.py`
Also, if you modify the UI file, then you would need
to run the previous command again.
examples/charts/chartthemes/chartthemes.pyproject 0000664 0000000 0000000 00000000074 13766170131 0022745 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "README.md", "themewidget.ui"]
}
examples/charts/chartthemes/main.py 0000664 0000000 0000000 00000036400 13766170131 0017775 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Chart Themes example from Qt v5.x"""
import sys
from PySide2.QtCore import QPointF, Qt
from PySide2.QtGui import QColor, QPainter, QPalette
from PySide2.QtWidgets import (QApplication, QMainWindow, QSizePolicy,
QWidget)
from PySide2.QtCharts import QtCharts
from ui_themewidget import Ui_ThemeWidgetForm as ui
from random import random, uniform
class ThemeWidget(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
self.charts = []
self.ui = ui()
self.list_count = 3
self.value_max = 10
self.value_count = 7
self.data_table = self.generate_random_data(self.list_count,
self.value_max, self.value_count)
self.ui.setupUi(self)
self.populate_themebox()
self.populate_animationbox()
self.populate_legendbox()
# Area Chart
chart_view = QtCharts.QChartView(self.create_areachart())
self.ui.gridLayout.addWidget(chart_view, 1, 0)
self.charts.append(chart_view)
# Pie Chart
chart_view = QtCharts.QChartView(self.createPieChart())
chart_view.setSizePolicy(QSizePolicy.Ignored,
QSizePolicy.Ignored)
self.ui.gridLayout.addWidget(chart_view, 1, 1)
self.charts.append(chart_view)
# Line Chart
chart_view = QtCharts.QChartView(self.createLineChart())
self.ui.gridLayout.addWidget(chart_view, 1, 2)
self.charts.append(chart_view)
# Bar Chart
chart_view = QtCharts.QChartView(self.createBarChart())
self.ui.gridLayout.addWidget(chart_view, 2, 0)
self.charts.append(chart_view)
# Spline Chart
chart_view = QtCharts.QChartView(self.createSplineChart())
self.ui.gridLayout.addWidget(chart_view, 2, 1)
self.charts.append(chart_view)
# Scatter Chart
chart_view = QtCharts.QChartView(self.create_scatterchart())
self.ui.gridLayout.addWidget(chart_view, 2, 2)
self.charts.append(chart_view)
# Set defaults
self.ui.antialiasCheckBox.setChecked(True)
# Set the colors from the light theme as default ones
pal = qApp.palette()
pal.setColor(QPalette.Window, QColor(0xf0f0f0))
pal.setColor(QPalette.WindowText, QColor(0x404044))
qApp.setPalette(pal)
self.updateUI()
def generate_random_data(self, list_count, value_max, value_count):
data_table = []
for i in range(list_count):
data_list = []
y_value = 0
for j in range(value_count):
constant = value_max / float(value_count)
y_value += uniform(0, constant)
x_value = (j + random()) * constant
value = QPointF(x_value, y_value)
label = "Slice {}: {}".format(i, j)
data_list.append((value, label))
data_table.append(data_list)
return data_table
def populate_themebox(self):
theme = self.ui.themeComboBox
theme.addItem("Light", QtCharts.QChart.ChartThemeLight)
theme.addItem("Blue Cerulean", QtCharts.QChart.ChartThemeBlueCerulean)
theme.addItem("Dark", QtCharts.QChart.ChartThemeDark)
theme.addItem("Brown Sand", QtCharts.QChart.ChartThemeBrownSand)
theme.addItem("Blue NCS", QtCharts.QChart.ChartThemeBlueNcs)
theme.addItem("High Contrast", QtCharts.QChart.ChartThemeHighContrast)
theme.addItem("Blue Icy", QtCharts.QChart.ChartThemeBlueIcy)
theme.addItem("Qt", QtCharts.QChart.ChartThemeQt)
def populate_animationbox(self):
animated = self.ui.animatedComboBox
animated.addItem("No Animations", QtCharts.QChart.NoAnimation)
animated.addItem("GridAxis Animations", QtCharts.QChart.GridAxisAnimations)
animated.addItem("Series Animations", QtCharts.QChart.SeriesAnimations)
animated.addItem("All Animations", QtCharts.QChart.AllAnimations)
def populate_legendbox(self):
legend = self.ui.legendComboBox
legend.addItem("No Legend ", 0)
legend.addItem("Legend Top", Qt.AlignTop)
legend.addItem("Legend Bottom", Qt.AlignBottom)
legend.addItem("Legend Left", Qt.AlignLeft)
legend.addItem("Legend Right", Qt.AlignRight)
def create_areachart(self):
chart = QtCharts.QChart()
chart.setTitle("Area Chart")
# The lower series initialized to zero values
lower_series = None
name = "Series "
for i in range(len(self.data_table)):
upper_series = QtCharts.QLineSeries(chart)
for j in range(len(self.data_table[i])):
data = self.data_table[i][j]
if lower_series:
points = lower_series.pointsVector()
y_value = points[i].y() + data[0].y()
upper_series.append(QPointF(j, y_value))
else:
upper_series.append(QPointF(j, data[0].y()))
area = QtCharts.QAreaSeries(upper_series, lower_series)
area.setName("{}{}".format(name, i))
chart.addSeries(area)
lower_series = upper_series
chart.createDefaultAxes()
chart.axisX().setRange(0, self.value_count - 1)
chart.axisY().setRange(0, self.value_max)
# Add space to label to add space between labels and axis
chart.axisY().setLabelFormat("%.1f ")
return chart
def createBarChart(self):
chart = QtCharts.QChart()
chart.setTitle("Bar chart")
series = QtCharts.QStackedBarSeries(chart)
for i in range(len(self.data_table)):
barset = QtCharts.QBarSet("Bar set {}".format(i))
for data in self.data_table[i]:
barset.append(data[0].y())
series.append(barset)
chart.addSeries(series)
chart.createDefaultAxes()
chart.axisY().setRange(0, self.value_max * 2)
# Add space to label to add space between labels and axis
chart.axisY().setLabelFormat("%.1f ")
return chart
def createLineChart(self):
chart = QtCharts.QChart()
chart.setTitle("Line chart")
name = "Series "
for i, lst in enumerate(self.data_table):
series = QtCharts.QLineSeries(chart)
for data in lst:
series.append(data[0])
series.setName("{}{}".format(name, i))
chart.addSeries(series)
chart.createDefaultAxes()
chart.axisX().setRange(0, self.value_max)
chart.axisY().setRange(0, self.value_count)
# Add space to label to add space between labels and axis
chart.axisY().setLabelFormat("%.1f ")
return chart
def createPieChart(self):
chart = QtCharts.QChart()
chart.setTitle("Pie chart")
series = QtCharts.QPieSeries(chart)
for data in self.data_table[0]:
slc = series.append(data[1], data[0].y())
if data == self.data_table[0][0]:
# Show the first slice exploded with label
slc.setLabelVisible()
slc.setExploded()
slc.setExplodeDistanceFactor(0.5)
series.setPieSize(0.4)
chart.addSeries(series)
return chart
def createSplineChart(self):
chart = QtCharts.QChart()
chart.setTitle("Spline chart")
name = "Series "
for i, lst in enumerate(self.data_table):
series = QtCharts.QSplineSeries(chart)
for data in lst:
series.append(data[0])
series.setName("{}{}".format(name, i))
chart.addSeries(series)
chart.createDefaultAxes()
chart.axisX().setRange(0, self.value_max)
chart.axisY().setRange(0, self.value_count)
# Add space to label to add space between labels and axis
chart.axisY().setLabelFormat("%.1f ")
return chart
def create_scatterchart(self):
chart = QtCharts.QChart()
chart.setTitle("Scatter chart")
name = "Series "
for i, lst in enumerate(self.data_table):
series = QtCharts.QScatterSeries(chart)
for data in lst:
series.append(data[0])
series.setName("{}{}".format(name, i))
chart.addSeries(series)
chart.createDefaultAxes()
chart.axisX().setRange(0, self.value_max)
chart.axisY().setRange(0, self.value_count)
# Add space to label to add space between labels and axis
chart.axisY().setLabelFormat("%.1f ")
return chart
def updateUI(self):
def set_colors(window_color, text_color):
pal = self.window().palette()
pal.setColor(QPalette.Window, window_color)
pal.setColor(QPalette.WindowText, text_color)
self.window().setPalette(pal)
idx = self.ui.themeComboBox.currentIndex()
theme = self.ui.themeComboBox.itemData(idx)
if len(self.charts):
chart_theme = self.charts[0].chart().theme()
if chart_theme != theme:
for chart_view in self.charts:
if theme == 0:
theme_name = QtCharts.QChart.ChartThemeLight
elif theme == 1:
theme_name = QtCharts.QChart.ChartThemeBlueCerulean
elif theme == 2:
theme_name = QtCharts.QChart.ChartThemeDark
elif theme == 3:
theme_name = QtCharts.QChart.ChartThemeBrownSand
elif theme == 4:
theme_name = QtCharts.QChart.ChartThemeBlueNcs
elif theme == 5:
theme_name = QtCharts.QChart.ChartThemeHighContrast
elif theme == 6:
theme_name = QtCharts.QChart.ChartThemeBlueIcy
elif theme == 7:
theme_name = QtCharts.QChart.ChartThemeQt
else:
theme_name = QtCharts.QChart.ChartThemeLight
chart_view.chart().setTheme(theme_name)
# Set palette colors based on selected theme
if theme == QtCharts.QChart.ChartThemeLight:
set_colors(QColor(0xf0f0f0), QColor(0x404044))
elif theme == QtCharts.QChart.ChartThemeDark:
set_colors(QColor(0x121218), QColor(0xd6d6d6))
elif theme == QtCharts.QChart.ChartThemeBlueCerulean:
set_colors(QColor(0x40434a), QColor(0xd6d6d6))
elif theme == QtCharts.QChart.ChartThemeBrownSand:
set_colors(QColor(0x9e8965), QColor(0x404044))
elif theme == QtCharts.QChart.ChartThemeBlueNcs:
set_colors(QColor(0x018bba), QColor(0x404044))
elif theme == QtCharts.QChart.ChartThemeHighContrast:
set_colors(QColor(0xffab03), QColor(0x181818))
elif theme == QtCharts.QChart.ChartThemeBlueIcy:
set_colors(QColor(0xcee7f0), QColor(0x404044))
else:
set_colors(QColor(0xf0f0f0), QColor(0x404044))
# Update antialiasing
checked = self.ui.antialiasCheckBox.isChecked()
for chart in self.charts:
chart.setRenderHint(QPainter.Antialiasing, checked)
# Update animation options
idx = self.ui.animatedComboBox.currentIndex()
options = self.ui.animatedComboBox.itemData(idx)
if len(self.charts):
chart = self.charts[0].chart()
animation_options = chart.animationOptions()
if animation_options != options:
for chart_view in self.charts:
options_name = QtCharts.QChart.NoAnimation
if options == 0:
options_name = QtCharts.QChart.NoAnimation
elif options == 1:
options_name = QtCharts.QChart.GridAxisAnimations
elif options == 2:
options_name = QtCharts.QChart.SeriesAnimations
elif options == 3:
options_name = QtCharts.QChart.AllAnimations
chart_view.chart().setAnimationOptions(options_name)
# Update legend alignment
idx = self.ui.legendComboBox.currentIndex()
alignment = self.ui.legendComboBox.itemData(idx)
if not alignment:
for chart_view in self.charts:
chart_view.chart().legend().hide()
else:
for chart_view in self.charts:
alignment_name = Qt.AlignTop
if alignment == 32:
alignment_name = Qt.AlignTop
elif alignment == 64:
alignment_name = Qt.AlignBottom
elif alignment == 1:
alignment_name = Qt.AlignLeft
elif alignment == 2:
alignment_name = Qt.AlignRight
chart_view.chart().legend().setAlignment(alignment_name)
chart_view.chart().legend().show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = QMainWindow()
widget = ThemeWidget(None)
window.setCentralWidget(widget)
available_geometry = app.desktop().availableGeometry(window)
size = available_geometry.height() * 0.75
window.setFixedSize(size, size * 0.8)
window.show()
sys.exit(app.exec_())
examples/charts/chartthemes/themewidget.ui 0000664 0000000 0000000 00000005101 13766170131 0021336 0 ustar 00root root 0000000 0000000
ThemeWidgetForm00900600Theme:Animation:Legend:Anti-aliasingfalseQt::Horizontal4020themeComboBoxcurrentIndexChanged(int)ThemeWidgetFormupdateUI()antialiasCheckBoxtoggled(bool)ThemeWidgetFormupdateUI()legendComboBoxcurrentIndexChanged(int)ThemeWidgetFormupdateUI()animatedComboBoxcurrentIndexChanged(int)ThemeWidgetFormupdateUI()updateUI()
examples/charts/chartthemes/ui_themewidget.py 0000664 0000000 0000000 00000006574 13766170131 0022065 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'themewidget.ui'
##
## Created by: Qt User Interface Compiler version 5.14.0
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PySide2.QtGui import (QColor, QFont, QIcon, QPixmap)
from PySide2.QtWidgets import *
class Ui_ThemeWidgetForm(object):
def setupUi(self, ThemeWidgetForm):
if ThemeWidgetForm.objectName():
ThemeWidgetForm.setObjectName(u"ThemeWidgetForm")
ThemeWidgetForm.resize(900, 600)
self.gridLayout = QGridLayout(ThemeWidgetForm)
self.gridLayout.setObjectName(u"gridLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.themeLabel = QLabel(ThemeWidgetForm)
self.themeLabel.setObjectName(u"themeLabel")
self.horizontalLayout.addWidget(self.themeLabel)
self.themeComboBox = QComboBox(ThemeWidgetForm)
self.themeComboBox.setObjectName(u"themeComboBox")
self.horizontalLayout.addWidget(self.themeComboBox)
self.animatedLabel = QLabel(ThemeWidgetForm)
self.animatedLabel.setObjectName(u"animatedLabel")
self.horizontalLayout.addWidget(self.animatedLabel)
self.animatedComboBox = QComboBox(ThemeWidgetForm)
self.animatedComboBox.setObjectName(u"animatedComboBox")
self.horizontalLayout.addWidget(self.animatedComboBox)
self.legendLabel = QLabel(ThemeWidgetForm)
self.legendLabel.setObjectName(u"legendLabel")
self.horizontalLayout.addWidget(self.legendLabel)
self.legendComboBox = QComboBox(ThemeWidgetForm)
self.legendComboBox.setObjectName(u"legendComboBox")
self.horizontalLayout.addWidget(self.legendComboBox)
self.antialiasCheckBox = QCheckBox(ThemeWidgetForm)
self.antialiasCheckBox.setObjectName(u"antialiasCheckBox")
self.antialiasCheckBox.setChecked(False)
self.horizontalLayout.addWidget(self.antialiasCheckBox)
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(self.horizontalSpacer)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 3)
self.retranslateUi(ThemeWidgetForm)
self.themeComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI)
self.antialiasCheckBox.toggled.connect(ThemeWidgetForm.updateUI)
self.legendComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI)
self.animatedComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI)
QMetaObject.connectSlotsByName(ThemeWidgetForm)
# setupUi
def retranslateUi(self, ThemeWidgetForm):
self.themeLabel.setText(QCoreApplication.translate("ThemeWidgetForm", u"Theme:", None))
self.animatedLabel.setText(QCoreApplication.translate("ThemeWidgetForm", u"Animation:", None))
self.legendLabel.setText(QCoreApplication.translate("ThemeWidgetForm", u"Legend:", None))
self.antialiasCheckBox.setText(QCoreApplication.translate("ThemeWidgetForm", u"Anti-aliasing", None))
# retranslateUi
examples/charts/donutbreakdown.py 0000664 0000000 0000000 00000015567 13766170131 0017603 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Donut Chart Breakdown example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt
from PySide2.QtGui import QColor, QFont, QPainter
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCharts import QtCharts
class MainSlice(QtCharts.QPieSlice):
def __init__(self, breakdown_series, parent=None):
super(MainSlice, self).__init__(parent)
self.breakdown_series = breakdown_series
self.name = None
self.percentageChanged.connect(self.update_label)
def get_breakdown_series(self):
return self.breakdown_series
def setName(self, name):
self.name = name
def name(self):
return self.name
def update_label(self):
self.setLabel("{} {:.2f}%".format(self.name,
self.percentage() * 100))
class DonutBreakdownChart(QtCharts.QChart):
def __init__(self, parent=None):
super(DonutBreakdownChart, self).__init__(QtCharts.QChart.ChartTypeCartesian, parent, Qt.WindowFlags())
self.main_series = QtCharts.QPieSeries()
self.main_series.setPieSize(0.7)
self.addSeries(self.main_series)
def add_breakdown_series(self, breakdown_series, color):
font = QFont("Arial", 8)
# add breakdown series as a slice to center pie
main_slice = MainSlice(breakdown_series)
main_slice.setName(breakdown_series.name())
main_slice.setValue(breakdown_series.sum())
self.main_series.append(main_slice)
# customize the slice
main_slice.setBrush(color)
main_slice.setLabelVisible()
main_slice.setLabelColor(Qt.white)
main_slice.setLabelPosition(QtCharts.QPieSlice.LabelInsideHorizontal)
main_slice.setLabelFont(font)
# position and customize the breakdown series
breakdown_series.setPieSize(0.8)
breakdown_series.setHoleSize(0.7)
breakdown_series.setLabelsVisible()
for pie_slice in breakdown_series.slices():
color = QColor(color).lighter(115)
pie_slice.setBrush(color)
pie_slice.setLabelFont(font)
# add the series to the chart
self.addSeries(breakdown_series)
# recalculate breakdown donut segments
self.recalculate_angles()
# update customize legend markers
self.update_legend_markers()
def recalculate_angles(self):
angle = 0
slices = self.main_series.slices()
for pie_slice in slices:
breakdown_series = pie_slice.get_breakdown_series()
breakdown_series.setPieStartAngle(angle)
angle += pie_slice.percentage() * 360.0 # full pie is 360.0
breakdown_series.setPieEndAngle(angle)
def update_legend_markers(self):
# go through all markers
for series in self.series():
markers = self.legend().markers(series)
for marker in markers:
if series == self.main_series:
# hide markers from main series
marker.setVisible(False)
else:
# modify markers from breakdown series
marker.setLabel("{} {:.2f}%".format(
marker.slice().label(),
marker.slice().percentage() * 100, 0))
marker.setFont(QFont("Arial", 8))
if __name__ == "__main__":
app = QApplication(sys.argv)
# Graph is based on data of:
# 'Total consumption of energy increased by 10 per cent in 2010'
# Statistics Finland, 13 December 2011
# http://www.stat.fi/til/ekul/2010/ekul_2010_2011-12-13_tie_001_en.html
series1 = QtCharts.QPieSeries()
series1.setName("Fossil fuels")
series1.append("Oil", 353295)
series1.append("Coal", 188500)
series1.append("Natural gas", 148680)
series1.append("Peat", 94545)
series2 = QtCharts.QPieSeries()
series2.setName("Renewables")
series2.append("Wood fuels", 319663)
series2.append("Hydro power", 45875)
series2.append("Wind power", 1060)
series3 = QtCharts.QPieSeries()
series3.setName("Others")
series3.append("Nuclear energy", 238789)
series3.append("Import energy", 37802)
series3.append("Other", 32441)
donut_breakdown = DonutBreakdownChart()
donut_breakdown.setAnimationOptions(QtCharts.QChart.AllAnimations)
donut_breakdown.setTitle("Total consumption of energy in Finland 2010")
donut_breakdown.legend().setAlignment(Qt.AlignRight)
donut_breakdown.add_breakdown_series(series1, Qt.red)
donut_breakdown.add_breakdown_series(series2, Qt.darkGreen)
donut_breakdown.add_breakdown_series(series3, Qt.darkBlue)
window = QMainWindow()
chart_view = QtCharts.QChartView(donut_breakdown)
chart_view.setRenderHint(QPainter.Antialiasing)
window.setCentralWidget(chart_view)
available_geometry = app.desktop().availableGeometry(window)
size = available_geometry.height() * 0.75
window.resize(size, size * 0.8)
window.show()
sys.exit(app.exec_())
examples/charts/legend.py 0000664 0000000 0000000 00000022510 13766170131 0015775 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Legend example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt, QRectF
from PySide2.QtGui import QBrush, QColor, QPainter, QPen
from PySide2.QtWidgets import (QApplication, QDoubleSpinBox,
QFormLayout, QGridLayout, QGroupBox, QPushButton, QWidget)
from PySide2.QtCharts import QtCharts
class MainWidget(QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.chart = QtCharts.QChart()
self.series = QtCharts.QBarSeries()
self.main_layout = QGridLayout()
self.button_layout = QGridLayout()
self.font_layout = QFormLayout()
self.font_size = QDoubleSpinBox()
self.legend_posx = QDoubleSpinBox()
self.legend_posy = QDoubleSpinBox()
self.legend_width = QDoubleSpinBox()
self.legend_height = QDoubleSpinBox()
self.detach_legend_button = QPushButton("Toggle attached")
self.detach_legend_button.clicked.connect(self.toggle_attached)
self.button_layout.addWidget(self.detach_legend_button, 0, 0)
self.add_set_button = QPushButton("add barset")
self.add_set_button.clicked.connect(self.add_barset)
self.button_layout.addWidget(self.add_set_button, 2, 0)
self.remove_barset_button = QPushButton("remove barset")
self.remove_barset_button.clicked.connect(self.remove_barset)
self.button_layout.addWidget(self.remove_barset_button, 3, 0)
self.align_button = QPushButton("Align (Bottom)")
self.align_button.clicked.connect(self.set_legend_alignment)
self.button_layout.addWidget(self.align_button, 4, 0)
self.bold_button = QPushButton("Toggle bold")
self.bold_button.clicked.connect(self.toggle_bold)
self.button_layout.addWidget(self.bold_button, 8, 0)
self.italic_button = QPushButton("Toggle italic")
self.italic_button.clicked.connect(self.toggle_italic)
self.button_layout.addWidget(self.italic_button, 9, 0)
self.legend_posx.valueChanged.connect(self.update_legend_layout)
self.legend_posy.valueChanged.connect(self.update_legend_layout)
self.legend_width.valueChanged.connect(self.update_legend_layout)
self.legend_height.valueChanged.connect(self.update_legend_layout)
legend_layout = QFormLayout()
legend_layout.addRow("HPos", self.legend_posx)
legend_layout.addRow("VPos", self.legend_posy)
legend_layout.addRow("Width", self.legend_width)
legend_layout.addRow("Height", self.legend_height)
self.legend_settings = QGroupBox("Detached legend")
self.legend_settings.setLayout(legend_layout)
self.button_layout.addWidget(self.legend_settings)
self.legend_settings.setVisible(False)
# Create chart view with the chart
self.chart_view = QtCharts.QChartView(self.chart, self)
# Create spinbox to modify font size
self.font_size.setValue(self.chart.legend().font().pointSizeF())
self.font_size.valueChanged.connect(self.font_size_changed)
self.font_layout.addRow("Legend font size", self.font_size)
# Create layout for grid and detached legend
self.main_layout.addLayout(self.button_layout, 0, 0)
self.main_layout.addLayout(self.font_layout, 1, 0)
self.main_layout.addWidget(self.chart_view, 0, 1, 3, 1)
self.setLayout(self.main_layout)
self.create_series()
def create_series(self):
self.add_barset()
self.add_barset()
self.add_barset()
self.add_barset()
self.chart.addSeries(self.series)
self.chart.setTitle("Legend detach example")
self.chart.createDefaultAxes()
self.chart.legend().setVisible(True)
self.chart.legend().setAlignment(Qt.AlignBottom)
self.chart_view.setRenderHint(QPainter.Antialiasing)
def show_legend_spinbox(self):
self.legend_settings.setVisible(True)
chart_viewrect = self.chart_view.rect()
self.legend_posx.setMinimum(0)
self.legend_posx.setMaximum(chart_viewrect.width())
self.legend_posx.setValue(150)
self.legend_posy.setMinimum(0)
self.legend_posy.setMaximum(chart_viewrect.height())
self.legend_posy.setValue(150)
self.legend_width.setMinimum(0)
self.legend_width.setMaximum(chart_viewrect.width())
self.legend_width.setValue(150)
self.legend_height.setMinimum(0)
self.legend_height.setMaximum(chart_viewrect.height())
self.legend_height.setValue(75)
def hideLegendSpinbox(self):
self.legend_settings.setVisible(False)
def toggle_attached(self):
legend = self.chart.legend()
if legend.isAttachedToChart():
legend.detachFromChart()
legend.setBackgroundVisible(True)
legend.setBrush(QBrush(QColor(128, 128, 128, 128)))
legend.setPen(QPen(QColor(192, 192, 192, 192)))
self.show_legend_spinbox()
self.update_legend_layout()
else:
legend.attachToChart()
legend.setBackgroundVisible(False)
self.hideLegendSpinbox()
self.update()
def add_barset(self):
series_count = self.series.count()
bar_set = QtCharts.QBarSet("set {}".format(series_count))
delta = series_count * 0.1
bar_set.append([1 + delta, 2 + delta, 3 + delta, 4 + delta])
self.series.append(bar_set)
def remove_barset(self):
sets = self.series.barSets()
len_sets = len(sets)
if len_sets > 0:
self.series.remove(sets[len_sets - 1])
def set_legend_alignment(self):
button = self.sender()
legend = self.chart.legend()
alignment = legend.alignment()
if alignment == Qt.AlignTop:
legend.setAlignment(Qt.AlignLeft)
if button:
button.setText("Align (Left)")
elif alignment == Qt.AlignLeft:
legend.setAlignment(Qt.AlignBottom)
if button:
button.setText("Align (Bottom)")
elif alignment == Qt.AlignBottom:
legend.setAlignment(Qt.AlignRight)
if button:
button.setText("Align (Right)")
else:
if button:
button.setText("Align (Top)")
legend.setAlignment(Qt.AlignTop)
def toggle_bold(self):
legend = self.chart.legend()
font = legend.font()
font.setBold(not font.bold())
legend.setFont(font)
def toggle_italic(self):
legend = self.chart.legend()
font = legend.font()
font.setItalic(not font.italic())
legend.setFont(font)
def font_size_changed(self):
legend = self.chart.legend()
font = legend.font()
font_size = self.font_size.value()
if font_size < 1:
font_size = 1
font.setPointSizeF(font_size)
legend.setFont(font)
def update_legend_layout(self):
legend = self.chart.legend()
rect = QRectF(self.legend_posx.value(),
self.legend_posy.value(),
self.legend_width.value(),
self.legend_height.value())
legend.setGeometry(rect)
legend.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWidget()
available_geometry = app.desktop().availableGeometry(w)
size = available_geometry.height() * 0.75
w.setFixedSize(size, size)
w.show()
sys.exit(app.exec_())
examples/charts/lineandbar.py 0000664 0000000 0000000 00000010615 13766170131 0016641 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the 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_())
examples/charts/linechart.py 0000664 0000000 0000000 00000006273 13766170131 0016520 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the linechart example from Qt v5.x"""
import sys
from PySide2.QtCore import QPointF
from PySide2.QtGui import QPainter
from PySide2.QtWidgets import QMainWindow, QApplication
from PySide2.QtCharts import QtCharts
class TestChart(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.series = QtCharts.QLineSeries()
self.series.append(0, 6)
self.series.append(2, 4)
self.series.append(3, 8)
self.series.append(7, 4)
self.series.append(10, 5)
self.series.append(QPointF(11, 1))
self.series.append(QPointF(13, 3))
self.series.append(QPointF(17, 6))
self.series.append(QPointF(18, 3))
self.series.append(QPointF(20, 2))
self.chart = QtCharts.QChart()
self.chart.legend().hide()
self.chart.addSeries(self.series)
self.chart.createDefaultAxes()
self.chart.setTitle("Simple line chart example")
self.chartView = QtCharts.QChartView(self.chart)
self.chartView.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(self.chartView)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TestChart()
window.show()
window.resize(440, 300)
sys.exit(app.exec_())
examples/charts/logvalueaxis.py 0000664 0000000 0000000 00000007030 13766170131 0017242 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Logarithmic Axis Example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt, QPointF
from PySide2.QtGui import QPainter
from PySide2.QtWidgets import QMainWindow, QApplication
from PySide2.QtCharts import QtCharts
class TestChart(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.series = QtCharts.QLineSeries()
self.series.append([
QPointF(1.0, 1.0), QPointF(2.0, 73.0), QPointF(3.0, 268.0),
QPointF(4.0, 17.0), QPointF(5.0, 4325.0), QPointF(6.0, 723.0)])
self.chart = QtCharts.QChart()
self.chart.addSeries(self.series)
self.chart.legend().hide()
self.chart.setTitle("Logarithmic axis example")
self.axisX = QtCharts.QValueAxis()
self.axisX.setTitleText("Data point")
self.axisX.setLabelFormat("%i")
self.axisX.setTickCount(self.series.count())
self.chart.addAxis(self.axisX, Qt.AlignBottom)
self.series.attachAxis(self.axisX)
self.axisY = QtCharts.QLogValueAxis()
self.axisY.setTitleText("Values")
self.axisY.setLabelFormat("%g")
self.axisY.setBase(8.0)
self.axisY.setMinorTickCount(-1)
self.chart.addAxis(self.axisY, Qt.AlignLeft)
self.series.attachAxis(self.axisY)
self.chartView = QtCharts.QChartView(self.chart)
self.chartView.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(self.chartView)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TestChart()
window.show()
window.resize(800, 600)
sys.exit(app.exec_())
examples/charts/memoryusage.py 0000664 0000000 0000000 00000011630 13766170131 0017075 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 Charts example: Simple memory usage viewer"""
import os
import sys
from PySide2.QtCore import QProcess
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCharts import QtCharts
def runProcess(command, arguments):
process = QProcess()
process.start(command, arguments)
process.waitForFinished()
std_output = process.readAllStandardOutput().data().decode('utf-8')
return std_output.split('\n')
def getMemoryUsage():
result = []
if sys.platform == 'win32':
# Windows: Obtain memory usage in KB from 'tasklist'
for line in runProcess('tasklist', [])[3:]:
if len(line) >= 74:
command = line[0:23].strip()
if command.endswith('.exe'):
command = command[0:len(command) - 4]
memoryUsage = float(line[64:74].strip().replace(',', '').replace('.', ''))
legend = ''
if memoryUsage > 10240:
legend = '{} {}M'.format(command, round(memoryUsage / 1024))
else:
legend = '{} {}K'.format(command, round(memoryUsage))
result.append([legend, memoryUsage])
else:
# Unix: Obtain memory usage percentage from 'ps'
psOptions = ['-e', 'v']
memoryColumn = 8
commandColumn = 9
if sys.platform == 'darwin':
psOptions = ['-e', '-v']
memoryColumn = 11
commandColumn = 12
for line in runProcess('ps', psOptions):
tokens = line.split(None)
if len(tokens) > commandColumn and "PID" not in tokens: # Percentage and command
command = tokens[commandColumn]
if not command.startswith('['):
command = os.path.basename(command)
memoryUsage = round(float(tokens[memoryColumn].replace(',', '.')))
legend = '{} {}%'.format(command, memoryUsage)
result.append([legend, memoryUsage])
result.sort(key = lambda x: x[1], reverse=True)
return result
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Memory Usage')
memoryUsage = getMemoryUsage()
if len(memoryUsage) > 5:
memoryUsage = memoryUsage[0:4]
self.series = QtCharts.QPieSeries()
for item in memoryUsage:
self.series.append(item[0], item[1])
slice = self.series.slices()[0]
slice.setExploded()
slice.setLabelVisible()
self.chart = QtCharts.QChart()
self.chart.addSeries(self.series)
self.chartView = QtCharts.QChartView(self.chart)
self.setCentralWidget(self.chartView)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
availableGeometry = app.desktop().availableGeometry(mainWin)
size = availableGeometry.height() * 3 / 4
mainWin.resize(size, size)
mainWin.show()
sys.exit(app.exec_())
examples/charts/modeldata.py 0000664 0000000 0000000 00000015220 13766170131 0016471 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Model Data example from Qt v5.x"""
import sys
from random import randrange
from PySide2.QtCore import QAbstractTableModel, QModelIndex, QRect, Qt
from PySide2.QtGui import QColor, QPainter
from PySide2.QtWidgets import (QApplication, QGridLayout, QHeaderView,
QTableView, QWidget)
from PySide2.QtCharts import QtCharts
class CustomTableModel(QAbstractTableModel):
def __init__(self):
QAbstractTableModel.__init__(self)
self.input_data = []
self.mapping = {}
self.column_count = 4
self.row_count = 15
for i in range(self.row_count):
data_vec = [0]*self.column_count
for k in range(len(data_vec)):
if k % 2 == 0:
data_vec[k] = i * 50 + randrange(30)
else:
data_vec[k] = randrange(100)
self.input_data.append(data_vec)
def rowCount(self, parent=QModelIndex()):
return len(self.input_data)
def columnCount(self, parent=QModelIndex()):
return self.column_count
def headerData(self, section, orientation, role):
if role != Qt.DisplayRole:
return None
if orientation == Qt.Horizontal:
if section % 2 == 0:
return "x"
else:
return "y"
else:
return "{}".format(section + 1)
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return self.input_data[index.row()][index.column()]
elif role == Qt.EditRole:
return self.input_data[index.row()][index.column()]
elif role == Qt.BackgroundRole:
for color, rect in self.mapping.items():
if rect.contains(index.column(), index.row()):
return QColor(color)
# cell not mapped return white color
return QColor(Qt.white)
return None
def setData(self, index, value, role=Qt.EditRole):
if index.isValid() and role == Qt.EditRole:
self.input_data[index.row()][index.column()] = float(value)
self.dataChanged.emit(index, index)
return True
return False
def flags(self, index):
return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable
def add_mapping(self, color, area):
self.mapping[color] = area
def clear_mapping(self):
self.mapping = {}
class TableWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.model = CustomTableModel()
self.table_view = QTableView()
self.table_view.setModel(self.model)
self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.chart = QtCharts.QChart()
self.chart.setAnimationOptions(QtCharts.QChart.AllAnimations)
self.series = QtCharts.QLineSeries()
self.series.setName("Line 1")
self.mapper = QtCharts.QVXYModelMapper(self)
self.mapper.setXColumn(0)
self.mapper.setYColumn(1)
self.mapper.setSeries(self.series)
self.mapper.setModel(self.model)
self.chart.addSeries(self.series)
# for storing color hex from the series
seriesColorHex = "#000000"
# get the color of the series and use it for showing the mapped area
seriesColorHex = "{}".format(self.series.pen().color().name())
self.model.add_mapping(seriesColorHex, QRect(0, 0, 2, self.model.rowCount()))
# series 2
self.series = QtCharts.QLineSeries()
self.series.setName("Line 2")
self.mapper = QtCharts.QVXYModelMapper(self)
self.mapper.setXColumn(2)
self.mapper.setYColumn(3)
self.mapper.setSeries(self.series)
self.mapper.setModel(self.model)
self.chart.addSeries(self.series)
# get the color of the series and use it for showing the mapped area
seriesColorHex = "{}".format(self.series.pen().color().name())
self.model.add_mapping(seriesColorHex, QRect(2, 0, 2, self.model.rowCount()))
self.chart.createDefaultAxes()
self.chart_view = QtCharts.QChartView(self.chart)
self.chart_view.setRenderHint(QPainter.Antialiasing)
self.chart_view.setMinimumSize(640, 480)
# create main layout
self.main_layout = QGridLayout()
self.main_layout.addWidget(self.table_view, 1, 0)
self.main_layout.addWidget(self.chart_view, 1, 1)
self.main_layout.setColumnStretch(1, 1)
self.main_layout.setColumnStretch(0, 0)
self.setLayout(self.main_layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = TableWidget()
w.show()
sys.exit(app.exec_())
examples/charts/nesteddonuts.py 0000664 0000000 0000000 00000012063 13766170131 0017260 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Nested Donuts example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt, QTimer
from PySide2.QtGui import QPainter
from PySide2.QtWidgets import QApplication, QGridLayout, QWidget
from PySide2.QtCharts import QtCharts
from random import randrange
from functools import partial
class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.setMinimumSize(800, 600)
self.donuts = []
self.chart_view = QtCharts.QChartView()
self.chart_view.setRenderHint(QPainter.Antialiasing)
self.chart = self.chart_view.chart()
self.chart.legend().setVisible(False)
self.chart.setTitle("Nested donuts demo")
self.chart.setAnimationOptions(QtCharts.QChart.AllAnimations)
self.min_size = 0.1
self.max_size = 0.9
self.donut_count = 5
self.setup_donuts()
# create main layout
self.main_layout = QGridLayout(self)
self.main_layout.addWidget(self.chart_view, 1, 1)
self.setLayout(self.main_layout)
self.update_timer = QTimer(self)
self.update_timer.timeout.connect(self.update_rotation)
self.update_timer.start(1250)
def setup_donuts(self):
for i in range(self.donut_count):
donut = QtCharts.QPieSeries()
slccount = randrange(3, 6)
for j in range(slccount):
value = randrange(100, 200)
slc = QtCharts.QPieSlice(str(value), value)
slc.setLabelVisible(True)
slc.setLabelColor(Qt.white)
slc.setLabelPosition(QtCharts.QPieSlice.LabelInsideTangential)
# Connection using an extra parameter for the slot
slc.hovered[bool].connect(partial(self.explode_slice, slc=slc))
donut.append(slc)
size = (self.max_size - self.min_size)/self.donut_count
donut.setHoleSize(self.min_size + i * size)
donut.setPieSize(self.min_size + (i + 1) * size)
self.donuts.append(donut)
self.chart_view.chart().addSeries(donut)
def update_rotation(self):
for donut in self.donuts:
phase_shift = randrange(-50, 100)
donut.setPieStartAngle(donut.pieStartAngle() + phase_shift)
donut.setPieEndAngle(donut.pieEndAngle() + phase_shift)
def explode_slice(self, exploded, slc):
if exploded:
self.update_timer.stop()
slice_startangle = slc.startAngle()
slice_endangle = slc.startAngle() + slc.angleSpan()
donut = slc.series()
idx = self.donuts.index(donut)
for i in range(idx + 1, len(self.donuts)):
self.donuts[i].setPieStartAngle(slice_endangle)
self.donuts[i].setPieEndAngle(360 + slice_startangle)
else:
for donut in self.donuts:
donut.setPieStartAngle(0)
donut.setPieEndAngle(360)
self.update_timer.start()
slc.setExploded(exploded)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
examples/charts/percentbarchart.py 0000664 0000000 0000000 00000007147 13766170131 0017717 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Percent Bar Chart example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt
from PySide2.QtGui import QPainter
from PySide2.QtWidgets import (QMainWindow, QApplication)
from PySide2.QtCharts import QtCharts
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
set0 = QtCharts.QBarSet("Jane")
set1 = QtCharts.QBarSet("John")
set2 = QtCharts.QBarSet("Axel")
set3 = QtCharts.QBarSet("Mary")
set4 = QtCharts.QBarSet("Samantha")
set0.append([1, 2, 3, 4, 5, 6])
set1.append([5, 0, 0, 4, 0, 7])
set2.append([3, 5, 8, 13, 8, 5])
set3.append([5, 6, 7, 3, 4, 5])
set4.append([9, 7, 5, 3, 1, 2])
series = QtCharts.QPercentBarSeries()
series.append(set0)
series.append(set1)
series.append(set2)
series.append(set3)
series.append(set4)
chart = QtCharts.QChart()
chart.addSeries(series)
chart.setTitle("Simple percentbarchart example")
chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)
categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
axis = QtCharts.QBarCategoryAxis()
axis.append(categories)
chart.createDefaultAxes()
chart.setAxisX(axis, series)
chart.legend().setVisible(True)
chart.legend().setAlignment(Qt.AlignBottom)
chart_view = QtCharts.QChartView(chart)
chart_view.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(chart_view)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.resize(420, 300)
w.show()
sys.exit(app.exec_())
examples/charts/piechart.py 0000664 0000000 0000000 00000006243 13766170131 0016343 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Pie Chart Example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt
from PySide2.QtGui import QPainter, QPen
from PySide2.QtWidgets import QMainWindow, QApplication
from PySide2.QtCharts import QtCharts
class TestChart(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.series = QtCharts.QPieSeries()
self.series.append('Jane', 1)
self.series.append('Joe', 2)
self.series.append('Andy', 3)
self.series.append('Barbara', 4)
self.series.append('Axel', 5)
self.slice = self.series.slices()[1]
self.slice.setExploded()
self.slice.setLabelVisible()
self.slice.setPen(QPen(Qt.darkGreen, 2))
self.slice.setBrush(Qt.green)
self.chart = QtCharts.QChart()
self.chart.addSeries(self.series)
self.chart.setTitle('Simple piechart example')
self.chart.legend().hide()
self.chartView = QtCharts.QChartView(self.chart)
self.chartView.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(self.chartView)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TestChart()
window.show()
window.resize(440, 300)
sys.exit(app.exec_())
examples/charts/qmlpolarchart/ 0000775 0000000 0000000 00000000000 13766170131 0017036 5 ustar 00root root 0000000 0000000 examples/charts/qmlpolarchart/View1.qml 0000664 0000000 0000000 00000004471 13766170131 0020552 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtCharts 2.0
Item {
anchors.fill: parent
//![1]
PolarChartView {
title: "Two Series, Common Axes"
anchors.fill: parent
legend.visible: false
antialiasing: true
ValueAxis {
id: axisAngular
min: 0
max: 20
tickCount: 9
}
ValueAxis {
id: axisRadial
min: -0.5
max: 1.5
}
SplineSeries {
id: series1
axisAngular: axisAngular
axisRadial: axisRadial
pointsVisible: true
}
ScatterSeries {
id: series2
axisAngular: axisAngular
axisRadial: axisRadial
markerSize: 10
}
}
// Add data dynamically to the series
Component.onCompleted: {
for (var i = 0; i <= 20; i++) {
series1.append(i, Math.random());
series2.append(i, Math.random());
}
}
//![1]
}
examples/charts/qmlpolarchart/View2.qml 0000664 0000000 0000000 00000010011 13766170131 0020536 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtCharts 2.0
Item {
anchors.fill: parent
//![1]
PolarChartView {
title: "Historical Area Series"
anchors.fill: parent
legend.visible: false
antialiasing: true
DateTimeAxis {
id: axis1
format: "yyyy MMM"
tickCount: 13
}
ValueAxis {
id: axis2
}
LineSeries {
id: lowerLine
axisAngular: axis1
axisRadial: axis2
// Please note that month in JavaScript months are zero based, so 2 means March
XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 15 }
XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 35 }
XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 75 }
XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 102 }
XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 132 }
XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 120 }
XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 140 }
XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 150 }
}
LineSeries {
id: upperLine
axisAngular: axis1
axisRadial: axis2
// Please note that month in JavaScript months are zero based, so 2 means March
XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 30 }
XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 55 }
XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 80 }
XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 105 }
XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 125 }
XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 160 }
XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 140 }
XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 140 }
XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 170 }
XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 200 }
}
AreaSeries {
axisAngular: axis1
axisRadial: axis2
lowerSeries: lowerLine
upperSeries: upperLine
}
}
// DateTimeAxis is based on QDateTimes so we must convert our JavaScript dates to
// milliseconds since epoch to make them match the DateTimeAxis values
function toMsecsSinceEpoch(date) {
var msecs = date.getTime();
return msecs;
}
//![1]
}
examples/charts/qmlpolarchart/View3.qml 0000664 0000000 0000000 00000005342 13766170131 0020552 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtCharts 2.0
Item {
anchors.fill: parent
//![1]
PolarChartView {
title: "Numerical Data for Dummies"
anchors.fill: parent
legend.visible: false
antialiasing: true
LineSeries {
axisRadial: CategoryAxis {
min: 0
max: 30
CategoryRange {
label: "critical"
endValue: 2
}
CategoryRange {
label: "low"
endValue: 7
}
CategoryRange {
label: "normal"
endValue: 12
}
CategoryRange {
label: "high"
endValue: 18
}
CategoryRange {
label: "extremely high"
endValue: 30
}
}
axisAngular: ValueAxis {
tickCount: 13
}
XYPoint { x: 0; y: 4.3 }
XYPoint { x: 1; y: 4.1 }
XYPoint { x: 2; y: 4.7 }
XYPoint { x: 3; y: 3.9 }
XYPoint { x: 4; y: 5.2 }
XYPoint { x: 5; y: 5.3 }
XYPoint { x: 6; y: 6.1 }
XYPoint { x: 7; y: 7.7 }
XYPoint { x: 8; y: 12.9 }
XYPoint { x: 9; y: 19.2 }
}
}
//![1]
}
examples/charts/qmlpolarchart/main.qml 0000664 0000000 0000000 00000005363 13766170131 0020504 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Item {
width: 800
height: 600
property bool sourceLoaded: false
ListView {
id: root
focus: true
anchors.fill: parent
snapMode: ListView.SnapOneItem
highlightRangeMode: ListView.StrictlyEnforceRange
highlightMoveDuration: 250
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
onCurrentIndexChanged: {
if (infoText.opacity > 0.0) {
if (sourceLoaded)
infoText.opacity = 0.0;
else if (currentIndex != 0)
currentIndex = 0;
}
}
model: ListModel {
ListElement {component: "View1.qml"}
ListElement {component: "View2.qml"}
ListElement {component: "View3.qml"}
}
delegate: Loader {
width: root.width
height: root.height
source: component
asynchronous: true
onLoaded: sourceLoaded = true
}
}
Rectangle {
id: infoText
anchors.centerIn: parent
width: parent.width
height: 40
color: "black"
Text {
color: "white"
anchors.centerIn: parent
text: "You can navigate between views using swipe or arrow keys"
}
Behavior on opacity {
NumberAnimation { duration: 400 }
}
}
}
examples/charts/qmlpolarchart/qmlpolarchart.py 0000664 0000000 0000000 00000005144 13766170131 0022265 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the QML Polar Chart Example from Qt v5.x"""
import sys
import os
from PySide2.QtQuick import QQuickView
from PySide2.QtCore import Qt, QUrl
from PySide2.QtWidgets import QApplication, QMainWindow
if __name__ == '__main__':
app = QApplication(sys.argv)
viewer = QQuickView()
viewer.engine().addImportPath(os.path.dirname(__file__))
viewer.engine().quit.connect(viewer.close)
viewer.setTitle = "QML Polar Chart"
qmlFile = os.path.join(os.path.dirname(__file__), 'main.qml')
viewer.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
viewer.setResizeMode(QQuickView.SizeRootObjectToView)
viewer.show()
sys.exit(app.exec_())
examples/charts/qmlpolarchart/qmlpolarchart.pyproject 0000664 0000000 0000000 00000000146 13766170131 0023651 0 ustar 00root root 0000000 0000000 {
"files": ["View1.qml", "View1.qml", "View2.qml", "View3.qml", "main.qml", "qmlpolarchart.py"]
}
examples/charts/temperaturerecords.py 0000664 0000000 0000000 00000007337 13766170131 0020470 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the Temperature Records example from Qt v5.x"""
import sys
from PySide2.QtCore import Qt
from PySide2.QtGui import QPainter
from PySide2.QtWidgets import QMainWindow, QApplication
from PySide2.QtCharts import QtCharts
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
low = QtCharts.QBarSet("Min")
high = QtCharts.QBarSet("Max")
low.append([-52, -50, -45.3, -37.0, -25.6, -8.0,
-6.0, -11.8, -19.7, -32.8, -43.0, -48.0])
high.append([11.9, 12.8, 18.5, 26.5, 32.0, 34.8,
38.2, 34.8, 29.8, 20.4, 15.1, 11.8])
series = QtCharts.QStackedBarSeries()
series.append(low)
series.append(high)
chart = QtCharts.QChart()
chart.addSeries(series)
chart.setTitle("Temperature records in celcius")
chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)
categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"]
axisX = QtCharts.QBarCategoryAxis()
axisX.append(categories)
axisX.setTitleText("Month")
chart.addAxis(axisX, Qt.AlignBottom)
axisY = QtCharts.QValueAxis()
axisY.setRange(-52, 52)
axisY.setTitleText("Temperature [°C]")
chart.addAxis(axisY, Qt.AlignLeft)
series.attachAxis(axisX)
series.attachAxis(axisY)
chart.legend().setVisible(True)
chart.legend().setAlignment(Qt.AlignBottom)
chart_view = QtCharts.QChartView(chart)
chart_view.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(chart_view)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.resize(600, 300)
w.show()
sys.exit(app.exec_())
examples/corelib/ 0000775 0000000 0000000 00000000000 13766170131 0014320 5 ustar 00root root 0000000 0000000 examples/corelib/threads/ 0000775 0000000 0000000 00000000000 13766170131 0015752 5 ustar 00root root 0000000 0000000 examples/corelib/threads/mandelbrot.py 0000664 0000000 0000000 00000027761 13766170131 0020470 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the corelib/threads/mandelbrot example from Qt v5.x, originating from PyQt"""
from PySide2.QtCore import (Signal, QMutex, QMutexLocker, QPoint, QSize, Qt,
QThread, QWaitCondition)
from PySide2.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
from PySide2.QtWidgets import QApplication, QWidget
DefaultCenterX = -0.647011
DefaultCenterY = -0.0395159
DefaultScale = 0.00403897
ZoomInFactor = 0.8
ZoomOutFactor = 1 / ZoomInFactor
ScrollStep = 20
class RenderThread(QThread):
ColormapSize = 512
renderedImage = Signal(QImage, float)
def __init__(self, parent=None):
super(RenderThread, self).__init__(parent)
self.mutex = QMutex()
self.condition = QWaitCondition()
self.centerX = 0.0
self.centerY = 0.0
self.scaleFactor = 0.0
self.resultSize = QSize()
self.colormap = []
self.restart = False
self.abort = False
for i in range(RenderThread.ColormapSize):
self.colormap.append(self.rgbFromWaveLength(380.0 + (i * 400.0 / RenderThread.ColormapSize)))
def stop(self):
self.mutex.lock()
self.abort = True
self.condition.wakeOne()
self.mutex.unlock()
self.wait(2000)
def render(self, centerX, centerY, scaleFactor, resultSize):
locker = QMutexLocker(self.mutex)
self.centerX = centerX
self.centerY = centerY
self.scaleFactor = scaleFactor
self.resultSize = resultSize
if not self.isRunning():
self.start(QThread.LowPriority)
else:
self.restart = True
self.condition.wakeOne()
def run(self):
while True:
self.mutex.lock()
resultSize = self.resultSize
scaleFactor = self.scaleFactor
centerX = self.centerX
centerY = self.centerY
self.mutex.unlock()
halfWidth = resultSize.width() // 2
halfHeight = resultSize.height() // 2
image = QImage(resultSize, QImage.Format_RGB32)
NumPasses = 8
curpass = 0
while curpass < NumPasses:
MaxIterations = (1 << (2 * curpass + 6)) + 32
Limit = 4
allBlack = True
for y in range(-halfHeight, halfHeight):
if self.restart:
break
if self.abort:
return
ay = 1j * (centerY + (y * scaleFactor))
for x in range(-halfWidth, halfWidth):
c0 = centerX + (x * scaleFactor) + ay
c = c0
numIterations = 0
while numIterations < MaxIterations:
numIterations += 1
c = c*c + c0
if abs(c) >= Limit:
break
numIterations += 1
c = c*c + c0
if abs(c) >= Limit:
break
numIterations += 1
c = c*c + c0
if abs(c) >= Limit:
break
numIterations += 1
c = c*c + c0
if abs(c) >= Limit:
break
if numIterations < MaxIterations:
image.setPixel(x + halfWidth, y + halfHeight,
self.colormap[numIterations % RenderThread.ColormapSize])
allBlack = False
else:
image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0))
if allBlack and curpass == 0:
curpass = 4
else:
if not self.restart:
self.renderedImage.emit(image, scaleFactor)
curpass += 1
self.mutex.lock()
if not self.restart:
self.condition.wait(self.mutex)
self.restart = False
self.mutex.unlock()
def rgbFromWaveLength(self, wave):
r = 0.0
g = 0.0
b = 0.0
if wave >= 380.0 and wave <= 440.0:
r = -1.0 * (wave - 440.0) / (440.0 - 380.0)
b = 1.0
elif wave >= 440.0 and wave <= 490.0:
g = (wave - 440.0) / (490.0 - 440.0)
b = 1.0
elif wave >= 490.0 and wave <= 510.0:
g = 1.0
b = -1.0 * (wave - 510.0) / (510.0 - 490.0)
elif wave >= 510.0 and wave <= 580.0:
r = (wave - 510.0) / (580.0 - 510.0)
g = 1.0
elif wave >= 580.0 and wave <= 645.0:
r = 1.0
g = -1.0 * (wave - 645.0) / (645.0 - 580.0)
elif wave >= 645.0 and wave <= 780.0:
r = 1.0
s = 1.0
if wave > 700.0:
s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0)
elif wave < 420.0:
s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0)
r = pow(r * s, 0.8)
g = pow(g * s, 0.8)
b = pow(b * s, 0.8)
return qRgb(r*255, g*255, b*255)
class MandelbrotWidget(QWidget):
def __init__(self, parent=None):
super(MandelbrotWidget, self).__init__(parent)
self.thread = RenderThread()
self.pixmap = QPixmap()
self.pixmapOffset = QPoint()
self.lastDragPos = QPoint()
self.centerX = DefaultCenterX
self.centerY = DefaultCenterY
self.pixmapScale = DefaultScale
self.curScale = DefaultScale
self.thread.renderedImage.connect(self.updatePixmap)
self.setWindowTitle("Mandelbrot")
self.setCursor(Qt.CrossCursor)
self.resize(550, 400)
def paintEvent(self, event):
painter = QPainter(self)
painter.fillRect(self.rect(), Qt.black)
if self.pixmap.isNull():
painter.setPen(Qt.white)
painter.drawText(self.rect(), Qt.AlignCenter,
"Rendering initial image, please wait...")
return
if self.curScale == self.pixmapScale:
painter.drawPixmap(self.pixmapOffset, self.pixmap)
else:
scaleFactor = self.pixmapScale / self.curScale
newWidth = int(self.pixmap.width() * scaleFactor)
newHeight = int(self.pixmap.height() * scaleFactor)
newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2
newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2
painter.save()
painter.translate(newX, newY)
painter.scale(scaleFactor, scaleFactor)
exposed, _ = painter.matrix().inverted()
exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
painter.drawPixmap(exposed, self.pixmap, exposed)
painter.restore()
text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \
"hold left mouse button to scroll."
metrics = painter.fontMetrics()
textWidth = metrics.width(text)
painter.setPen(Qt.NoPen)
painter.setBrush(QColor(0, 0, 0, 127))
painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10,
metrics.lineSpacing() + 5)
painter.setPen(Qt.white)
painter.drawText((self.width() - textWidth) / 2,
metrics.leading() + metrics.ascent(), text)
def resizeEvent(self, event):
self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
def keyPressEvent(self, event):
if event.key() == Qt.Key_Plus:
self.zoom(ZoomInFactor)
elif event.key() == Qt.Key_Minus:
self.zoom(ZoomOutFactor)
elif event.key() == Qt.Key_Left:
self.scroll(-ScrollStep, 0)
elif event.key() == Qt.Key_Right:
self.scroll(+ScrollStep, 0)
elif event.key() == Qt.Key_Down:
self.scroll(0, -ScrollStep)
elif event.key() == Qt.Key_Up:
self.scroll(0, +ScrollStep)
else:
super(MandelbrotWidget, self).keyPressEvent(event)
def wheelEvent(self, event):
numDegrees = event.angleDelta().y() / 8
numSteps = numDegrees / 15.0
self.zoom(pow(ZoomInFactor, numSteps))
def mousePressEvent(self, event):
if event.buttons() == Qt.LeftButton:
self.lastDragPos = QPoint(event.pos())
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.pixmapOffset += event.pos() - self.lastDragPos
self.lastDragPos = QPoint(event.pos())
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.pixmapOffset += event.pos() - self.lastDragPos
self.lastDragPos = QPoint()
deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x()
deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y()
self.scroll(deltaX, deltaY)
def updatePixmap(self, image, scaleFactor):
if not self.lastDragPos.isNull():
return
self.pixmap = QPixmap.fromImage(image)
self.pixmapOffset = QPoint()
self.lastDragPosition = QPoint()
self.pixmapScale = scaleFactor
self.update()
def zoom(self, zoomFactor):
self.curScale *= zoomFactor
self.update()
self.thread.render(self.centerX, self.centerY, self.curScale,
self.size())
def scroll(self, deltaX, deltaY):
self.centerX += deltaX * self.curScale
self.centerY += deltaY * self.curScale
self.update()
self.thread.render(self.centerX, self.centerY, self.curScale,
self.size())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
widget = MandelbrotWidget()
widget.show()
r = app.exec_()
widget.thread.stop()
sys.exit(r)
examples/corelib/threads/threads.pyproject 0000664 0000000 0000000 00000000043 13766170131 0021342 0 ustar 00root root 0000000 0000000 {
"files": ["mandelbrot.py"]
}
examples/corelib/tools/ 0000775 0000000 0000000 00000000000 13766170131 0015460 5 ustar 00root root 0000000 0000000 examples/corelib/tools/codecs/ 0000775 0000000 0000000 00000000000 13766170131 0016720 5 ustar 00root root 0000000 0000000 examples/corelib/tools/codecs/codecs.py 0000664 0000000 0000000 00000021357 13766170131 0020542 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the widgets/tools/codecs example from Qt v5.x"""
from PySide2 import QtCore, QtWidgets
def codec_name(codec):
try:
# Python v3.
name = str(codec.name(), encoding='ascii')
except TypeError:
# Python v2.
name = str(codec.name())
return name
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.textEdit = QtWidgets.QTextEdit()
self.textEdit.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setCentralWidget(self.textEdit)
self.codecs = []
self.findCodecs()
self.previewForm = PreviewForm(self)
self.previewForm.setCodecList(self.codecs)
self.saveAsActs = []
self.createActions()
self.createMenus()
self.setWindowTitle("Codecs")
self.resize(500, 400)
def open(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self)
if fileName:
inFile = QtCore.QFile(fileName)
if not inFile.open(QtCore.QFile.ReadOnly):
QtWidgets.QMessageBox.warning(self, "Codecs",
"Cannot read file %s:\n%s" % (fileName, inFile.errorString()))
return
data = inFile.readAll()
self.previewForm.setEncodedData(data)
if self.previewForm.exec_():
self.textEdit.setPlainText(self.previewForm.decodedString())
def save(self):
fileName = QtWidgets.QFileDialog.getSaveFileName(self)
if fileName:
outFile = QtCore.QFile(fileName)
if not outFile.open(QtCore.QFile.WriteOnly|QtCore.QFile.Text):
QtWidgets.QMessageBox.warning(self, "Codecs",
"Cannot write file %s:\n%s" % (fileName, outFile.errorString()))
return
action = self.sender()
codecName = action.data()
out = QtCore.QTextStream(outFile)
out.setCodec(codecName)
out << self.textEdit.toPlainText()
def about(self):
QtWidgets.QMessageBox.about(self, "About Codecs",
"The Codecs example demonstrates how to read and "
"write files using various encodings.")
def aboutToShowSaveAsMenu(self):
currentText = self.textEdit.toPlainText()
for action in self.saveAsActs:
codecName = str(action.data())
codec = QtCore.QTextCodec.codecForName(codecName)
action.setVisible(codec and codec.canEncode(currentText))
def findCodecs(self):
codecMap = []
iso8859RegExp = QtCore.QRegularExpression('^ISO[- ]8859-([0-9]+).*$')
assert iso8859RegExp.isValid()
for mib in QtCore.QTextCodec.availableMibs():
codec = QtCore.QTextCodec.codecForMib(mib)
sortKey = codec_name(codec).upper()
rank = 0
if sortKey.startswith('UTF-8'):
rank = 1
elif sortKey.startswith('UTF-16'):
rank = 2
else:
match = iso8859RegExp.match(sortKey)
if match.hasMatch():
if len(match.captured(1)) == 1:
rank = 3
else:
rank = 4
else:
rank = 5
codecMap.append((str(rank) + sortKey, codec))
codecMap.sort()
self.codecs = [item[-1] for item in codecMap]
def createActions(self):
self.openAct = QtWidgets.QAction("&Open...", self, shortcut="Ctrl+O",
triggered=self.open)
for codec in self.codecs:
name = codec_name(codec)
action = QtWidgets.QAction(name + '...', self, triggered=self.save)
action.setData(name)
self.saveAsActs.append(action)
self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q",
triggered=self.close)
self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)
self.aboutQtAct = QtWidgets.QAction("About &Qt", self,
triggered=qApp.aboutQt)
def createMenus(self):
self.saveAsMenu = QtWidgets.QMenu("&Save As", self)
for action in self.saveAsActs:
self.saveAsMenu.addAction(action)
self.saveAsMenu.aboutToShow.connect(self.aboutToShowSaveAsMenu)
self.fileMenu = QtWidgets.QMenu("&File", self)
self.fileMenu.addAction(self.openAct)
self.fileMenu.addMenu(self.saveAsMenu)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct)
self.helpMenu = QtWidgets.QMenu("&Help", self)
self.helpMenu.addAction(self.aboutAct)
self.helpMenu.addAction(self.aboutQtAct)
self.menuBar().addMenu(self.fileMenu)
self.menuBar().addSeparator()
self.menuBar().addMenu(self.helpMenu)
class PreviewForm(QtWidgets.QDialog):
def __init__(self, parent):
super(PreviewForm, self).__init__(parent)
self.encodingComboBox = QtWidgets.QComboBox()
encodingLabel = QtWidgets.QLabel("&Encoding:")
encodingLabel.setBuddy(self.encodingComboBox)
self.textEdit = QtWidgets.QTextEdit()
self.textEdit.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.textEdit.setReadOnly(True)
buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
self.encodingComboBox.activated.connect(self.updateTextEdit)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
mainLayout = QtWidgets.QGridLayout()
mainLayout.addWidget(encodingLabel, 0, 0)
mainLayout.addWidget(self.encodingComboBox, 0, 1)
mainLayout.addWidget(self.textEdit, 1, 0, 1, 2)
mainLayout.addWidget(buttonBox, 2, 0, 1, 2)
self.setLayout(mainLayout)
self.setWindowTitle("Choose Encoding")
self.resize(400, 300)
def setCodecList(self, codecs):
self.encodingComboBox.clear()
for codec in codecs:
self.encodingComboBox.addItem(codec_name(codec), codec.mibEnum())
def setEncodedData(self, data):
self.encodedData = data
self.updateTextEdit()
def decodedString(self):
return self.decodedStr
def updateTextEdit(self):
mib = self.encodingComboBox.itemData(self.encodingComboBox.currentIndex())
codec = QtCore.QTextCodec.codecForMib(mib)
data = QtCore.QTextStream(self.encodedData)
data.setAutoDetectUnicode(False)
data.setCodec(codec)
self.decodedStr = data.readAll()
self.textEdit.setPlainText(self.decodedStr)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
examples/corelib/tools/codecs/codecs.pyproject 0000664 0000000 0000000 00000000037 13766170131 0022121 0 ustar 00root root 0000000 0000000 {
"files": ["codecs.py"]
}
examples/corelib/tools/regexp.py 0000664 0000000 0000000 00000017670 13766170131 0017337 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the widgets/tools/regexp example from Qt v5.x"""
from PySide2 import QtCore, QtGui, QtWidgets
class RegExpDialog(QtWidgets.QDialog):
MaxCaptures = 6
def __init__(self, parent=None):
super(RegExpDialog, self).__init__(parent)
self.patternComboBox = QtWidgets.QComboBox()
self.patternComboBox.setEditable(True)
self.patternComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Preferred)
patternLabel = QtWidgets.QLabel("&Pattern:")
patternLabel.setBuddy(self.patternComboBox)
self.escapedPatternLineEdit = QtWidgets.QLineEdit()
self.escapedPatternLineEdit.setReadOnly(True)
palette = self.escapedPatternLineEdit.palette()
palette.setBrush(QtGui.QPalette.Base,
palette.brush(QtGui.QPalette.Disabled, QtGui.QPalette.Base))
self.escapedPatternLineEdit.setPalette(palette)
escapedPatternLabel = QtWidgets.QLabel("&Escaped Pattern:")
escapedPatternLabel.setBuddy(self.escapedPatternLineEdit)
self.syntaxComboBox = QtWidgets.QComboBox()
self.syntaxComboBox.addItem("Regular expression v1",
QtCore.QRegExp.RegExp)
self.syntaxComboBox.addItem("Regular expression v2",
QtCore.QRegExp.RegExp2)
self.syntaxComboBox.addItem("Wildcard", QtCore.QRegExp.Wildcard)
self.syntaxComboBox.addItem("Fixed string",
QtCore.QRegExp.FixedString)
syntaxLabel = QtWidgets.QLabel("&Pattern Syntax:")
syntaxLabel.setBuddy(self.syntaxComboBox)
self.textComboBox = QtWidgets.QComboBox()
self.textComboBox.setEditable(True)
self.textComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Preferred)
textLabel = QtWidgets.QLabel("&Text:")
textLabel.setBuddy(self.textComboBox)
self.caseSensitiveCheckBox = QtWidgets.QCheckBox("Case &Sensitive")
self.caseSensitiveCheckBox.setChecked(True)
self.minimalCheckBox = QtWidgets.QCheckBox("&Minimal")
indexLabel = QtWidgets.QLabel("Index of Match:")
self.indexEdit = QtWidgets.QLineEdit()
self.indexEdit.setReadOnly(True)
matchedLengthLabel = QtWidgets.QLabel("Matched Length:")
self.matchedLengthEdit = QtWidgets.QLineEdit()
self.matchedLengthEdit.setReadOnly(True)
self.captureLabels = []
self.captureEdits = []
for i in range(self.MaxCaptures):
self.captureLabels.append(QtWidgets.QLabel("Capture %d:" % i))
self.captureEdits.append(QtWidgets.QLineEdit())
self.captureEdits[i].setReadOnly(True)
self.captureLabels[0].setText("Match:")
checkBoxLayout = QtWidgets.QHBoxLayout()
checkBoxLayout.addWidget(self.caseSensitiveCheckBox)
checkBoxLayout.addWidget(self.minimalCheckBox)
checkBoxLayout.addStretch(1)
mainLayout = QtWidgets.QGridLayout()
mainLayout.addWidget(patternLabel, 0, 0)
mainLayout.addWidget(self.patternComboBox, 0, 1)
mainLayout.addWidget(escapedPatternLabel, 1, 0)
mainLayout.addWidget(self.escapedPatternLineEdit, 1, 1)
mainLayout.addWidget(syntaxLabel, 2, 0)
mainLayout.addWidget(self.syntaxComboBox, 2, 1)
mainLayout.addLayout(checkBoxLayout, 3, 0, 1, 2)
mainLayout.addWidget(textLabel, 4, 0)
mainLayout.addWidget(self.textComboBox, 4, 1)
mainLayout.addWidget(indexLabel, 5, 0)
mainLayout.addWidget(self.indexEdit, 5, 1)
mainLayout.addWidget(matchedLengthLabel, 6, 0)
mainLayout.addWidget(self.matchedLengthEdit, 6, 1)
for i in range(self.MaxCaptures):
mainLayout.addWidget(self.captureLabels[i], 7 + i, 0)
mainLayout.addWidget(self.captureEdits[i], 7 + i, 1)
self.setLayout(mainLayout)
self.patternComboBox.editTextChanged.connect(self.refresh)
self.textComboBox.editTextChanged.connect(self.refresh)
self.caseSensitiveCheckBox.toggled.connect(self.refresh)
self.minimalCheckBox.toggled.connect(self.refresh)
self.syntaxComboBox.currentIndexChanged.connect(self.refresh)
self.patternComboBox.addItem("[A-Za-z_]+([A-Za-z_0-9]*)")
self.textComboBox.addItem("(10 + delta4)* 32")
self.setWindowTitle("RegExp")
self.setFixedHeight(self.sizeHint().height())
self.refresh()
def refresh(self):
self.setUpdatesEnabled(False)
pattern = self.patternComboBox.currentText()
text = self.textComboBox.currentText()
escaped = str(pattern)
escaped.replace('\\', '\\\\')
escaped.replace('"', '\\"')
self.escapedPatternLineEdit.setText('"' + escaped + '"')
rx = QtCore.QRegExp(pattern)
cs = QtCore.Qt.CaseInsensitive
if self.caseSensitiveCheckBox.isChecked():
cs = QtCore.Qt.CaseSensitive
rx.setCaseSensitivity(cs)
rx.setMinimal(self.minimalCheckBox.isChecked())
syntax = self.syntaxComboBox.itemData(self.syntaxComboBox.currentIndex())
rx.setPatternSyntax(QtCore.QRegExp.PatternSyntax(syntax))
palette = self.patternComboBox.palette()
if rx.isValid():
palette.setColor(QtGui.QPalette.Text,
self.textComboBox.palette().color(QtGui.QPalette.Text))
else:
palette.setColor(QtGui.QPalette.Text, QtCore.Qt.red)
self.patternComboBox.setPalette(palette)
self.indexEdit.setText(str(rx.indexIn(text)))
self.matchedLengthEdit.setText(str(rx.matchedLength()))
for i in range(self.MaxCaptures):
self.captureLabels[i].setEnabled(i <= rx.captureCount())
self.captureEdits[i].setEnabled(i <= rx.captureCount())
self.captureEdits[i].setText(rx.cap(i))
self.setUpdatesEnabled(True)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
dialog = RegExpDialog()
sys.exit(dialog.exec_())
examples/corelib/tools/settingseditor/ 0000775 0000000 0000000 00000000000 13766170131 0020527 5 ustar 00root root 0000000 0000000 examples/corelib/tools/settingseditor/settingseditor.py 0000664 0000000 0000000 00000072206 13766170131 0024157 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the widgets/tools/settingseditor example from Qt v5.x"""
import sys
from PySide2.QtCore import (QByteArray, QDate, QDateTime, QDir, QEvent, QPoint,
QRect, QRegularExpression, QSettings, QSize, QTime, QTimer, Qt)
from PySide2.QtGui import (QColor, QIcon, QIntValidator, QDoubleValidator,
QRegularExpressionValidator, QValidator)
from PySide2.QtWidgets import (QAbstractItemView, QAction, QApplication,
QCheckBox, QComboBox, QFileDialog, QDialog, QDialogButtonBox, QGridLayout,
QGroupBox, QHeaderView, QInputDialog, QItemDelegate, QLabel, QLineEdit,
QMainWindow, QMessageBox, QStyle, QSpinBox, QStyleOptionViewItem,
QTableWidget, QTableWidgetItem, QTreeWidget, QTreeWidgetItem, QVBoxLayout)
class TypeChecker:
def __init__(self, parent=None):
self.bool_exp = QRegularExpression('^(true)|(false)$')
assert self.bool_exp.isValid()
self.bool_exp.setPatternOptions(QRegularExpression.CaseInsensitiveOption)
self.byteArray_exp = QRegularExpression(r'^[\x00-\xff]*$')
assert self.byteArray_exp.isValid()
self.char_exp = QRegularExpression('^.$')
assert self.char_exp.isValid()
pattern = r'^[+-]?\d+$'
self.int_exp = QRegularExpression(pattern)
assert self.int_exp.isValid()
pattern = r'^\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\)$'
self.color_exp = QRegularExpression(pattern)
assert self.color_exp.isValid()
pattern = r'^\((-?[0-9]*),(-?[0-9]*)\)$'
self.point_exp = QRegularExpression(pattern)
assert self.point_exp.isValid()
pattern = r'^\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\)$'
self.rect_exp = QRegularExpression(pattern)
assert self.rect_exp.isValid()
self.size_exp = QRegularExpression(self.point_exp)
date_pattern = '([0-9]{,4})-([0-9]{,2})-([0-9]{,2})'
self.date_exp = QRegularExpression('^{}$'.format(date_pattern))
assert self.date_exp.isValid()
time_pattern = '([0-9]{,2}):([0-9]{,2}):([0-9]{,2})'
self.time_exp = QRegularExpression('^{}$'.format(time_pattern))
assert self.time_exp.isValid()
pattern = '^{}T{}$'.format(date_pattern, time_pattern)
self.dateTime_exp = QRegularExpression(pattern)
assert self.dateTime_exp.isValid()
def type_from_text(self, text):
if self.bool_exp.match(text).hasMatch():
return bool
if self.int_exp.match(text).hasMatch():
return int
return None
def create_validator(self, value, parent):
if isinstance(value, bool):
return QRegularExpressionValidator(self.bool_exp, parent)
if isinstance(value, float):
return QDoubleValidator(parent)
if isinstance(value, int):
return QIntValidator(parent)
if isinstance(value, QByteArray):
return QRegularExpressionValidator(self.byteArray_exp, parent)
if isinstance(value, QColor):
return QRegularExpressionValidator(self.color_exp, parent)
if isinstance(value, QDate):
return QRegularExpressionValidator(self.date_exp, parent)
if isinstance(value, QDateTime):
return QRegularExpressionValidator(self.dateTime_exp, parent)
if isinstance(value, QTime):
return QRegularExpressionValidator(self.time_exp, parent)
if isinstance(value, QPoint):
return QRegularExpressionValidator(self.point_exp, parent)
if isinstance(value, QRect):
return QRegularExpressionValidator(self.rect_exp, parent)
if isinstance(value, QSize):
return QRegularExpressionValidator(self.size_exp, parent)
return None
def from_string(self, text, original_value):
if isinstance(original_value, QColor):
match = self.color_exp.match(text)
return QColor(min(int(match.captured(1)), 255),
min(int(match.captured(2)), 255),
min(int(match.captured(3)), 255),
min(int(match.captured(4)), 255))
if isinstance(original_value, QDate):
value = QDate.fromString(text, Qt.ISODate)
return value if value.isValid() else None
if isinstance(original_value, QDateTime):
value = QDateTime.fromString(text, Qt.ISODate)
return value if value.isValid() else None
if isinstance(original_value, QTime):
value = QTime.fromString(text, Qt.ISODate)
return value if value.isValid() else None
if isinstance(original_value, QPoint):
match = self.point_exp.match(text)
return QPoint(int(match.captured(1)),
int(match.captured(2)))
if isinstance(original_value, QRect):
match = self.rect_exp.match(text)
return QRect(int(match.captured(1)),
int(match.captured(2)),
int(match.captured(3)),
int(match.captured(4)))
if isinstance(original_value, QSize):
match = self.size_exp.match(text)
return QSize(int(match.captured(1)),
int(match.captured(2)))
if isinstance(original_value, list):
return text.split(',')
return type(original_value)(text)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.settings_tree = SettingsTree()
self.setCentralWidget(self.settings_tree)
self.location_dialog = None
self.create_actions()
self.create_menus()
self.auto_refresh_action.setChecked(True)
self.fallbacks_action.setChecked(True)
self.setWindowTitle("Settings Editor")
self.resize(500, 600)
def open_settings(self):
if self.location_dialog is None:
self.location_dialog = LocationDialog(self)
if self.location_dialog.exec_():
settings = QSettings(self.location_dialog.format(),
self.location_dialog.scope(),
self.location_dialog.organization(),
self.location_dialog.application())
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(True)
def open_inifile(self):
file_name, _ = QFileDialog.getOpenFileName(self, "Open INI File",
'', "INI Files (*.ini *.conf)")
if file_name:
self.load_ini_file(file_name)
def load_ini_file(self, file_name):
settings = QSettings(file_name, QSettings.IniFormat)
if settings.status() != QSettings.NoError:
return
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
def open_property_list(self):
file_name, _ = QFileDialog.getOpenFileName(self,
"Open Property List", '', "Property List Files (*.plist)")
if file_name:
settings = QSettings(file_name, QSettings.NativeFormat)
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
def open_registry_path(self):
path, ok = QInputDialog.getText(self, "Open Registry Path",
"Enter the path in the Windows registry:",
QLineEdit.Normal, 'HKEY_CURRENT_USER\\')
if ok and path != '':
settings = QSettings(path, QSettings.NativeFormat)
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
def about(self):
QMessageBox.about(self, "About Settings Editor",
"The Settings Editor example shows how to access "
"application settings using Qt.")
def create_actions(self):
self.open_settings_action = QAction("&Open Application Settings...",
self, shortcut="Ctrl+O", triggered=self.open_settings)
self.open_ini_file_action = QAction("Open I&NI File...", self,
shortcut="Ctrl+N", triggered=self.open_inifile)
self.open_property_list_action = QAction("Open macOS &Property List...",
self, shortcut="Ctrl+P", triggered=self.open_property_list)
if sys.platform != 'darwin':
self.open_property_list_action.setEnabled(False)
self.open_registry_path_action = QAction(
"Open Windows &Registry Path...", self, shortcut="Ctrl+G",
triggered=self.open_registry_path)
if sys.platform != 'win32':
self.open_registry_path_action.setEnabled(False)
self.refresh_action = QAction("&Refresh", self, shortcut="Ctrl+R",
enabled=False, triggered=self.settings_tree.refresh)
self.exit_action = QAction("E&xit", self, shortcut="Ctrl+Q",
triggered=self.close)
self.auto_refresh_action = QAction("&Auto-Refresh", self,
shortcut="Ctrl+A", checkable=True, enabled=False)
self.auto_refresh_action.triggered[bool].connect(self.settings_tree.set_auto_refresh)
self.auto_refresh_action.triggered[bool].connect(self.refresh_action.setDisabled)
self.fallbacks_action = QAction("&Fallbacks", self,
shortcut="Ctrl+F", checkable=True, enabled=False)
self.fallbacks_action.triggered[bool].connect(self.settings_tree.set_fallbacks_enabled)
self.about_action = QAction("&About", self, triggered=self.about)
self.about_Qt_action = QAction("About &Qt", self,
triggered=qApp.aboutQt)
def create_menus(self):
self.file_menu = self.menuBar().addMenu("&File")
self.file_menu.addAction(self.open_settings_action)
self.file_menu.addAction(self.open_ini_file_action)
self.file_menu.addAction(self.open_property_list_action)
self.file_menu.addAction(self.open_registry_path_action)
self.file_menu.addSeparator()
self.file_menu.addAction(self.refresh_action)
self.file_menu.addSeparator()
self.file_menu.addAction(self.exit_action)
self.options_menu = self.menuBar().addMenu("&Options")
self.options_menu.addAction(self.auto_refresh_action)
self.options_menu.addAction(self.fallbacks_action)
self.menuBar().addSeparator()
self.help_menu = self.menuBar().addMenu("&Help")
self.help_menu.addAction(self.about_action)
self.help_menu.addAction(self.about_Qt_action)
def set_settings_object(self, settings):
settings.setFallbacksEnabled(self.fallbacks_action.isChecked())
self.settings_tree.set_settings_object(settings)
self.refresh_action.setEnabled(True)
self.auto_refresh_action.setEnabled(True)
nice_name = QDir.fromNativeSeparators(settings.fileName())
nice_name = nice_name.split('/')[-1]
if not settings.isWritable():
nice_name += " (read only)"
self.setWindowTitle("{} - Settings Editor".format(nice_name))
class LocationDialog(QDialog):
def __init__(self, parent=None):
super(LocationDialog, self).__init__(parent)
self.format_combo = QComboBox()
self.format_combo.addItem("Native")
self.format_combo.addItem("INI")
self.scope_cCombo = QComboBox()
self.scope_cCombo.addItem("User")
self.scope_cCombo.addItem("System")
self.organization_combo = QComboBox()
self.organization_combo.addItem("Trolltech")
self.organization_combo.setEditable(True)
self.application_combo = QComboBox()
self.application_combo.addItem("Any")
self.application_combo.addItem("Application Example")
self.application_combo.addItem("Assistant")
self.application_combo.addItem("Designer")
self.application_combo.addItem("Linguist")
self.application_combo.setEditable(True)
self.application_combo.setCurrentIndex(3)
format_label = QLabel("&Format:")
format_label.setBuddy(self.format_combo)
scope_label = QLabel("&Scope:")
scope_label.setBuddy(self.scope_cCombo)
organization_label = QLabel("&Organization:")
organization_label.setBuddy(self.organization_combo)
application_label = QLabel("&Application:")
application_label.setBuddy(self.application_combo)
self.locations_groupbox = QGroupBox("Setting Locations")
self.locations_table = QTableWidget()
self.locations_table.setSelectionMode(QAbstractItemView.SingleSelection)
self.locations_table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.locations_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.locations_table.setColumnCount(2)
self.locations_table.setHorizontalHeaderLabels(("Location", "Access"))
self.locations_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
self.locations_table.horizontalHeader().resizeSection(1, 180)
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.format_combo.activated.connect(self.update_locations)
self.scope_cCombo.activated.connect(self.update_locations)
self.organization_combo.lineEdit().editingFinished.connect(self.update_locations)
self.application_combo.lineEdit().editingFinished.connect(self.update_locations)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
locations_layout = QVBoxLayout(self.locations_groupbox)
locations_layout.addWidget(self.locations_table)
mainLayout = QGridLayout(self)
mainLayout.addWidget(format_label, 0, 0)
mainLayout.addWidget(self.format_combo, 0, 1)
mainLayout.addWidget(scope_label, 1, 0)
mainLayout.addWidget(self.scope_cCombo, 1, 1)
mainLayout.addWidget(organization_label, 2, 0)
mainLayout.addWidget(self.organization_combo, 2, 1)
mainLayout.addWidget(application_label, 3, 0)
mainLayout.addWidget(self.application_combo, 3, 1)
mainLayout.addWidget(self.locations_groupbox, 4, 0, 1, 2)
mainLayout.addWidget(self.button_box, 5, 0, 1, 2)
self.update_locations()
self.setWindowTitle("Open Application Settings")
self.resize(650, 400)
def format(self):
if self.format_combo.currentIndex() == 0:
return QSettings.NativeFormat
else:
return QSettings.IniFormat
def scope(self):
if self.scope_cCombo.currentIndex() == 0:
return QSettings.UserScope
else:
return QSettings.SystemScope
def organization(self):
return self.organization_combo.currentText()
def application(self):
if self.application_combo.currentText() == "Any":
return ''
return self.application_combo.currentText()
def update_locations(self):
self.locations_table.setUpdatesEnabled(False)
self.locations_table.setRowCount(0)
for i in range(2):
if i == 0:
if self.scope() == QSettings.SystemScope:
continue
actualScope = QSettings.UserScope
else:
actualScope = QSettings.SystemScope
for j in range(2):
if j == 0:
if not self.application():
continue
actualApplication = self.application()
else:
actualApplication = ''
settings = QSettings(self.format(), actualScope,
self.organization(), actualApplication)
row = self.locations_table.rowCount()
self.locations_table.setRowCount(row + 1)
item0 = QTableWidgetItem()
item0.setText(settings.fileName())
item1 = QTableWidgetItem()
disable = not (settings.childKeys() or settings.childGroups())
if row == 0:
if settings.isWritable():
item1.setText("Read-write")
disable = False
else:
item1.setText("Read-only")
self.button_box.button(QDialogButtonBox.Ok).setDisabled(disable)
else:
item1.setText("Read-only fallback")
if disable:
item0.setFlags(item0.flags() & ~Qt.ItemIsEnabled)
item1.setFlags(item1.flags() & ~Qt.ItemIsEnabled)
self.locations_table.setItem(row, 0, item0)
self.locations_table.setItem(row, 1, item1)
self.locations_table.setUpdatesEnabled(True)
class SettingsTree(QTreeWidget):
def __init__(self, parent=None):
super(SettingsTree, self).__init__(parent)
self._type_checker = TypeChecker()
self.setItemDelegate(VariantDelegate(self._type_checker, self))
self.setHeaderLabels(("Setting", "Type", "Value"))
self.header().setSectionResizeMode(0, QHeaderView.Stretch)
self.header().setSectionResizeMode(2, QHeaderView.Stretch)
self.settings = None
self.refresh_timer = QTimer()
self.refresh_timer.setInterval(2000)
self.auto_refresh = False
self.group_icon = QIcon()
style = self.style()
self.group_icon.addPixmap(style.standardPixmap(QStyle.SP_DirClosedIcon),
QIcon.Normal, QIcon.Off)
self.group_icon.addPixmap(style.standardPixmap(QStyle.SP_DirOpenIcon),
QIcon.Normal, QIcon.On)
self.key_icon = QIcon()
self.key_icon.addPixmap(style.standardPixmap(QStyle.SP_FileIcon))
self.refresh_timer.timeout.connect(self.maybe_refresh)
def set_settings_object(self, settings):
self.settings = settings
self.clear()
if self.settings is not None:
self.settings.setParent(self)
self.refresh()
if self.auto_refresh:
self.refresh_timer.start()
else:
self.refresh_timer.stop()
def sizeHint(self):
return QSize(800, 600)
def set_auto_refresh(self, autoRefresh):
self.auto_refresh = autoRefresh
if self.settings is not None:
if self.auto_refresh:
self.maybe_refresh()
self.refresh_timer.start()
else:
self.refresh_timer.stop()
def set_fallbacks_enabled(self, enabled):
if self.settings is not None:
self.settings.setFallbacksEnabled(enabled)
self.refresh()
def maybe_refresh(self):
if self.state() != QAbstractItemView.EditingState:
self.refresh()
def refresh(self):
if self.settings is None:
return
# The signal might not be connected.
try:
self.itemChanged.disconnect(self.update_setting)
except:
pass
self.settings.sync()
self.update_child_items(None)
self.itemChanged.connect(self.update_setting)
def event(self, event):
if event.type() == QEvent.WindowActivate:
if self.isActiveWindow() and self.auto_refresh:
self.maybe_refresh()
return super(SettingsTree, self).event(event)
def update_setting(self, item):
key = item.text(0)
ancestor = item.parent()
while ancestor:
key = ancestor.text(0) + '/' + key
ancestor = ancestor.parent()
d = item.data(2, Qt.UserRole)
self.settings.setValue(key, item.data(2, Qt.UserRole))
if self.auto_refresh:
self.refresh()
def update_child_items(self, parent):
divider_index = 0
for group in self.settings.childGroups():
child_index = self.find_child(parent, group, divider_index)
if child_index != -1:
child = self.child_at(parent, child_index)
child.setText(1, '')
child.setText(2, '')
child.setData(2, Qt.UserRole, None)
self.move_item_forward(parent, child_index, divider_index)
else:
child = self.create_item(group, parent, divider_index)
child.setIcon(0, self.group_icon)
divider_index += 1
self.settings.beginGroup(group)
self.update_child_items(child)
self.settings.endGroup()
for key in self.settings.childKeys():
child_index = self.find_child(parent, key, 0)
if child_index == -1 or child_index >= divider_index:
if child_index != -1:
child = self.child_at(parent, child_index)
for i in range(child.childCount()):
self.delete_item(child, i)
self.move_item_forward(parent, child_index, divider_index)
else:
child = self.create_item(key, parent, divider_index)
child.setIcon(0, self.key_icon)
divider_index += 1
else:
child = self.child_at(parent, child_index)
value = self.settings.value(key)
if value is None:
child.setText(1, 'Invalid')
else:
# Try to convert to type unless a QByteArray is received
if isinstance(value, str):
value_type = self._type_checker.type_from_text(value)
if value_type:
value = self.settings.value(key, type=value_type)
child.setText(1, value.__class__.__name__)
child.setText(2, VariantDelegate.displayText(value))
child.setData(2, Qt.UserRole, value)
while divider_index < self.child_count(parent):
self.delete_item(parent, divider_index)
def create_item(self, text, parent, index):
after = None
if index != 0:
after = self.child_at(parent, index - 1)
if parent is not None:
item = QTreeWidgetItem(parent, after)
else:
item = QTreeWidgetItem(self, after)
item.setText(0, text)
item.setFlags(item.flags() | Qt.ItemIsEditable)
return item
def delete_item(self, parent, index):
if parent is not None:
item = parent.takeChild(index)
else:
item = self.takeTopLevelItem(index)
del item
def child_at(self, parent, index):
if parent is not None:
return parent.child(index)
else:
return self.topLevelItem(index)
def child_count(self, parent):
if parent is not None:
return parent.childCount()
else:
return self.topLevelItemCount()
def find_child(self, parent, text, startIndex):
for i in range(self.child_count(parent)):
if self.child_at(parent, i).text(0) == text:
return i
return -1
def move_item_forward(self, parent, oldIndex, newIndex):
for int in range(oldIndex - newIndex):
self.delete_item(parent, newIndex)
class VariantDelegate(QItemDelegate):
def __init__(self, type_checker, parent=None):
super(VariantDelegate, self).__init__(parent)
self._type_checker = type_checker
def paint(self, painter, option, index):
if index.column() == 2:
value = index.model().data(index, Qt.UserRole)
if not self.is_supported_type(value):
my_option = QStyleOptionViewItem(option)
my_option.state &= ~QStyle.State_Enabled
super(VariantDelegate, self).paint(painter, my_option, index)
return
super(VariantDelegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
if index.column() != 2:
return None
original_value = index.model().data(index, Qt.UserRole)
if not self.is_supported_type(original_value):
return None
editor = None
if isinstance(original_value, bool):
editor = QCheckBox(parent)
if isinstance(original_value, int):
editor = QSpinBox(parent)
editor.setRange(-32767, 32767)
else:
editor = QLineEdit(parent)
editor.setFrame(False)
validator = self._type_checker.create_validator(original_value, editor)
if validator:
editor.setValidator(validator)
return editor
def setEditorData(self, editor, index):
if not editor:
return
value = index.model().data(index, Qt.UserRole)
if isinstance(editor, QCheckBox):
editor.setCheckState(Qt.Checked if value else Qt.Unchecked)
elif isinstance(editor, QSpinBox):
editor.setValue(value)
else:
editor.setText(self.displayText(value))
def value_from_lineedit(self, lineedit, model, index):
if not lineedit.isModified():
return None
text = lineedit.text()
validator = lineedit.validator()
if validator is not None:
state, text, _ = validator.validate(text, 0)
if state != QValidator.Acceptable:
return None
original_value = index.model().data(index, Qt.UserRole)
return self._type_checker.from_string(text, original_value)
def setModelData(self, editor, model, index):
value = None
if isinstance(editor, QCheckBox):
value = editor.checkState() == Qt.Checked
elif isinstance(editor, QSpinBox):
value = editor.value()
else:
value = self.value_from_lineedit(editor, model, index)
if not value is None:
model.setData(index, value, Qt.UserRole)
model.setData(index, self.displayText(value), Qt.DisplayRole)
@staticmethod
def is_supported_type(value):
return isinstance(value, (bool, float, int, QByteArray, str, QColor,
QDate, QDateTime, QTime, QPoint, QRect,
QSize, list))
@staticmethod
def displayText(value):
if isinstance(value, str):
return value
if isinstance(value, bool):
return '✓' if value else '☐'
if isinstance(value, (int, float, QByteArray)):
return str(value)
if isinstance(value, QColor):
return '({},{},{},{})'.format(value.red(), value.green(),
value.blue(), value.alpha())
if isinstance(value, (QDate, QDateTime, QTime)):
return value.toString(Qt.ISODate)
if isinstance(value, QPoint):
return '({},{})'.format(value.x(), value.y())
if isinstance(value, QRect):
return '({},{},{},{})'.format(value.x(), value.y(), value.width(),
value.height())
if isinstance(value, QSize):
return '({},{})'.format(value.width(), value.height())
if isinstance(value, list):
return ','.join(value)
if value is None:
return ''
return '<{}>'.format(value)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_win = MainWindow()
if len(sys.argv) > 1:
main_win.load_ini_file(sys.argv[1])
main_win.show()
sys.exit(app.exec_())
examples/corelib/tools/settingseditor/settingseditor.pyproject 0000664 0000000 0000000 00000000047 13766170131 0025540 0 ustar 00root root 0000000 0000000 {
"files": ["settingseditor.py"]
}
examples/corelib/tools/tools.pyproject 0000664 0000000 0000000 00000000037 13766170131 0020561 0 ustar 00root root 0000000 0000000 {
"files": ["regexp.py"]
}
examples/datavisualization/ 0000775 0000000 0000000 00000000000 13766170131 0016434 5 ustar 00root root 0000000 0000000 examples/datavisualization/bars3d.py 0000664 0000000 0000000 00000010515 13766170131 0020166 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 QtDataVisualization example"""
import sys
from PySide2.QtCore import Qt
from PySide2.QtGui import QGuiApplication
from PySide2.QtWidgets import QApplication, QSizePolicy, QMainWindow, QWidget
from PySide2.QtDataVisualization import QtDataVisualization
def dataToBarDataRow(data):
return list(QtDataVisualization.QBarDataItem(d) for d in data)
def dataToBarDataArray(data):
return list(dataToBarDataRow(row) for row in data)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Qt DataVisualization 3D Bars')
self.bars = QtDataVisualization.Q3DBars()
self.columnAxis = QtDataVisualization.QCategory3DAxis()
self.columnAxis.setTitle('Columns')
self.columnAxis.setTitleVisible(True)
self.columnAxis.setLabels(['Column1', 'Column2'])
self.columnAxis.setLabelAutoRotation(30)
self.rowAxis = QtDataVisualization.QCategory3DAxis()
self.rowAxis.setTitle('Rows')
self.rowAxis.setTitleVisible(True)
self.rowAxis.setLabels(['Row1', 'Row2'])
self.rowAxis.setLabelAutoRotation(30)
self.valueAxis = QtDataVisualization.QValue3DAxis()
self.valueAxis.setTitle('Values')
self.valueAxis.setTitleVisible(True)
self.valueAxis.setRange(0, 5)
self.bars.setRowAxis(self.rowAxis)
self.bars.setColumnAxis(self.columnAxis)
self.bars.setValueAxis(self.valueAxis)
self.series = QtDataVisualization.QBar3DSeries()
self.arrayData = [[1, 2], [3, 4]]
self.series.dataProxy().addRows(dataToBarDataArray(self.arrayData))
self.bars.setPrimarySeries(self.series)
self.container = QWidget.createWindowContainer(self.bars)
if not self.bars.hasContext():
print("Couldn't initialize the OpenGL context.")
sys.exit(-1)
camera = self.bars.scene().activeCamera()
camera.setYRotation(22.5)
geometry = QGuiApplication.primaryScreen().geometry()
size = geometry.height() * 3 / 4
self.container.setMinimumSize(size, size)
self.container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.container.setFocusPolicy(Qt.StrongFocus)
self.setCentralWidget(self.container)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
examples/datavisualization/datavisualization.pyproject 0000664 0000000 0000000 00000000037 13766170131 0024130 0 ustar 00root root 0000000 0000000 {
"files": ["bars3d.py"]
}
examples/declarative/ 0000775 0000000 0000000 00000000000 13766170131 0015164 5 ustar 00root root 0000000 0000000 examples/declarative/declarative.pyproject 0000664 0000000 0000000 00000000077 13766170131 0021414 0 ustar 00root root 0000000 0000000 {
"files": ["view.qml", "scrolling.py", "usingmodel.py"]
}
examples/declarative/extending/ 0000775 0000000 0000000 00000000000 13766170131 0017151 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter1-basics/ 0000775 0000000 0000000 00000000000 13766170131 0022122 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter1-basics/app.qml 0000664 0000000 0000000 00000004561 13766170131 0023423 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![0]
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
PieChart {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
name: "A simple pie chart"
color: "red"
}
Text {
anchors {
bottom: parent.bottom;
horizontalCenter: parent.horizontalCenter;
bottomMargin: 20
}
text: aPieChart.name
}
}
//![0]
examples/declarative/extending/chapter1-basics/basics.py 0000664 0000000 0000000 00000007341 13766170131 0023745 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
"""PySide2 port of the qml/tutorials/extending-qml/chapter1-basics example from Qt v5.x"""
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
from utils import text_type
from PySide2.QtCore import Property, Signal, QUrl
from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide2.QtQml import qmlRegisterType
from PySide2.QtQuick import QQuickPaintedItem, QQuickView
class PieChart (QQuickPaintedItem):
def __init__(self, parent = None):
QQuickPaintedItem.__init__(self, parent)
self._name = u''
def paint(self, painter):
pen = QPen(self.color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.Antialiasing, True)
painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16)
def getColor(self):
return self._color
def setColor(self, value):
self._color = value
def getName(self):
return self._name
def setName(self, value):
self._name = value
nameChanged = Signal()
color = Property(QColor, getColor, setColor)
name = Property(text_type, getName, setName, notify=nameChanged)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart')
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/extending/chapter1-basics/chapter1-basics.pyproject 0000664 0000000 0000000 00000000052 13766170131 0027031 0 ustar 00root root 0000000 0000000 {
"files": ["basics.py", "app.qml"]
}
examples/declarative/extending/chapter2-methods/ 0000775 0000000 0000000 00000000000 13766170131 0022322 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter2-methods/app.qml 0000664 0000000 0000000 00000005004 13766170131 0023614 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![0]
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
PieChart {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
color: "red"
onChartCleared: console.log("The chart has been cleared")
}
MouseArea {
anchors.fill: parent
onClicked: aPieChart.clearChart()
}
Text {
anchors {
bottom: parent.bottom;
horizontalCenter: parent.horizontalCenter;
bottomMargin: 20
}
text: "Click anywhere to clear the chart"
}
}
//![0]
examples/declarative/extending/chapter2-methods/chapter2-methods.pyproject 0000664 0000000 0000000 00000000053 13766170131 0027432 0 ustar 00root root 0000000 0000000 {
"files": ["methods.py", "app.qml"]
}
examples/declarative/extending/chapter2-methods/methods.py 0000664 0000000 0000000 00000007607 13766170131 0024351 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
"""PySide2 port of the qml/tutorials/extending-qml/chapter2-methods example from Qt v5.x"""
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
from utils import text_type
from PySide2.QtCore import Property, Signal, Slot, QUrl, Qt
from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide2.QtQml import qmlRegisterType
from PySide2.QtQuick import QQuickPaintedItem, QQuickView
class PieChart (QQuickPaintedItem):
def __init__(self, parent = None):
QQuickPaintedItem.__init__(self, parent)
self._name = u''
def paint(self, painter):
pen = QPen(self.color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.Antialiasing, True)
painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16)
def getColor(self):
return self._color
def setColor(self, value):
self._color = value
def getName(self):
return self._name
def setName(self, value):
self._name = value
color = Property(QColor, getColor, setColor)
name = Property(text_type, getName, setName)
chartCleared = Signal()
@Slot() # This should be something like @Invokable
def clearChart(self):
self.setColor(Qt.transparent)
self.update()
self.chartCleared.emit()
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart')
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/extending/chapter3-bindings/ 0000775 0000000 0000000 00000000000 13766170131 0022455 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter3-bindings/app.qml 0000664 0000000 0000000 00000005172 13766170131 0023755 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![0]
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
Row {
anchors.centerIn: parent
spacing: 20
PieChart {
id: chartA
width: 100; height: 100
color: "red"
}
PieChart {
id: chartB
width: 100; height: 100
color: chartA.color
}
}
MouseArea {
anchors.fill: parent
onClicked: { chartA.color = "blue" }
}
Text {
anchors {
bottom: parent.bottom;
horizontalCenter: parent.horizontalCenter;
bottomMargin: 20
}
text: "Click anywhere to change the chart color"
}
}
//![0]
examples/declarative/extending/chapter3-bindings/bindings.py 0000664 0000000 0000000 00000010075 13766170131 0024627 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
"""PySide2 port of the qml/tutorials/extending-qml/chapter3-bindings example from Qt v5.x"""
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
from utils import text_type
from PySide2.QtCore import Property, Signal, Slot, QUrl, Qt
from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide2.QtQml import qmlRegisterType
from PySide2.QtQuick import QQuickPaintedItem, QQuickView
class PieChart (QQuickPaintedItem):
def __init__(self, parent = None):
QQuickPaintedItem.__init__(self, parent)
self._name = u''
self._color = QColor()
def paint(self, painter):
pen = QPen(self._color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.Antialiasing, True)
painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16)
def getColor(self):
return self._color
def setColor(self, value):
if value != self._color:
self._color = value
self.update()
self.colorChanged.emit()
def getName(self):
return self._name
def setName(self, value):
self._name = value
colorChanged = Signal()
color = Property(QColor, getColor, setColor, notify=colorChanged)
name = Property(text_type, getName, setName)
chartCleared = Signal()
@Slot() # This should be something like @Invokable
def clearChart(self):
self.setColor(Qt.transparent)
self.update()
self.chartCleared.emit()
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart')
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/extending/chapter3-bindings/chapter3-bindings.pyproject 0000664 0000000 0000000 00000000054 13766170131 0027721 0 ustar 00root root 0000000 0000000 {
"files": ["app.qml", "bindings.py"]
}
examples/declarative/extending/chapter4-customPropertyTypes/ 0000775 0000000 0000000 00000000000 13766170131 0024765 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter4-customPropertyTypes/app.qml 0000664 0000000 0000000 00000004453 13766170131 0026266 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![0]
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
PieChart {
id: chart
anchors.centerIn: parent
width: 100; height: 100
pieSlice: PieSlice {
anchors.fill: parent
color: "red"
}
}
Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color)
}
//![0]
examples/declarative/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject 0000664 0000000 0000000 00000000067 13766170131 0034545 0 ustar 00root root 0000000 0000000 {
"files": ["app.qml", "customPropertyTypes.py"]
}
examples/declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py 0000664 0000000 0000000 00000010220 13766170131 0031436 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
"""PySide2 port of the qml/tutorials/extending-qml/chapter4-customPropertyTypes example from Qt v5.x"""
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
from utils import text_type
from PySide2.QtCore import Property, QUrl
from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide2.QtQml import qmlRegisterType
from PySide2.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
class PieSlice (QQuickPaintedItem):
def __init__(self, parent = None):
QQuickPaintedItem.__init__(self, parent)
self._color = QColor()
def getColor(self):
return self._color
def setColor(self, value):
self._color = value
color = Property(QColor, getColor, setColor)
def paint(self, painter):
pen = QPen(self._color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.Antialiasing, True)
painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16)
class PieChart (QQuickItem):
def __init__(self, parent = None):
QQuickItem.__init__(self, parent)
self._name = None
self._pieSlice = None
def getName(self):
return self._name
def setName(self, value):
self._name = value
name = Property(text_type, getName, setName)
def getPieSlice(self):
return self._pieSlice
def setPieSlice(self, value):
self._pieSlice = value
self._pieSlice.setParentItem(self)
pieSlice = Property(PieSlice, getPieSlice, setPieSlice)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart')
qmlRegisterType(PieSlice, "Charts", 1, 0, "PieSlice")
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/extending/chapter5-listproperties/ 0000775 0000000 0000000 00000000000 13766170131 0023752 5 ustar 00root root 0000000 0000000 examples/declarative/extending/chapter5-listproperties/app.qml 0000664 0000000 0000000 00000005102 13766170131 0025243 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![0]
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
PieChart {
anchors.centerIn: parent
width: 100; height: 100
slices: [
PieSlice {
anchors.fill: parent
color: "red"
fromAngle: 0; angleSpan: 110
},
PieSlice {
anchors.fill: parent
color: "black"
fromAngle: 110; angleSpan: 50
},
PieSlice {
anchors.fill: parent
color: "blue"
fromAngle: 160; angleSpan: 100
}
]
}
}
//![0]
examples/declarative/extending/chapter5-listproperties/chapter5-listproperties.pyproject 0000664 0000000 0000000 00000000062 13766170131 0032512 0 ustar 00root root 0000000 0000000 {
"files": ["app.qml", "listproperties.py"]
}
examples/declarative/extending/chapter5-listproperties/listproperties.py 0000664 0000000 0000000 00000011015 13766170131 0027412 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
"""PySide2 port of the qml/tutorials/extending-qml/chapter5-listproperties example from Qt v5.x"""
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
from utils import text_type
from PySide2.QtCore import Property, QUrl
from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide2.QtQml import qmlRegisterType, ListProperty
from PySide2.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
class PieSlice (QQuickPaintedItem):
def __init__(self, parent = None):
QQuickPaintedItem.__init__(self, parent)
self._color = QColor()
self._fromAngle = 0
self._angleSpan = 0
def getColor(self):
return self._color
def setColor(self, value):
self._color = value
def getFromAngle(self):
return self._angle
def setFromAngle(self, value):
self._fromAngle = value
def getAngleSpan(self):
return self._angleSpan
def setAngleSpan(self, value):
self._angleSpan = value
color = Property(QColor, getColor, setColor)
fromAngle = Property(int, getFromAngle, setFromAngle)
angleSpan = Property(int, getAngleSpan, setAngleSpan)
def paint(self, painter):
pen = QPen(self._color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.Antialiasing, True)
painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), self._fromAngle * 16, self._angleSpan * 16)
class PieChart (QQuickItem):
def __init__(self, parent = None):
QQuickItem.__init__(self, parent)
self._name = u''
self._slices = []
def getName(self):
return self._name
def setName(self, value):
self._name = value
name = Property(text_type, getName, setName)
def appendSlice(self, _slice):
_slice.setParentItem(self)
self._slices.append(_slice)
slices = ListProperty(PieSlice, appendSlice)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart')
qmlRegisterType(PieSlice, "Charts", 1, 0, "PieSlice")
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/scrolling.py 0000664 0000000 0000000 00000005451 13766170131 0017537 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
# This example uses a QML file to show a scrolling list containing
# all the items listed in dataList.
if __name__ == '__main__':
dataList = ["Item 1", "Item 2", "Item 3", "Item 4"]
app = QGuiApplication(sys.argv)
view = QQuickView()
ctxt = view.rootContext()
ctxt.setContextProperty("myModel", dataList)
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
examples/declarative/signals/ 0000775 0000000 0000000 00000000000 13766170131 0016624 5 ustar 00root root 0000000 0000000 examples/declarative/signals/pytoqml1/ 0000775 0000000 0000000 00000000000 13766170131 0020412 5 ustar 00root root 0000000 0000000 examples/declarative/signals/pytoqml1/main.py 0000664 0000000 0000000 00000005320 13766170131 0021710 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QTimer, QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
timer = QTimer()
timer.start(2000)
view = QQuickView()
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
root = view.rootObject()
timer.timeout.connect(root.updateRotater)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/signals/pytoqml1/pytoqml1.pyproject 0000664 0000000 0000000 00000000051 13766170131 0024135 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/signals/pytoqml1/view.qml 0000664 0000000 0000000 00000005030 13766170131 0022075 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Rectangle {
id: page
function updateRotater() {
rotater.angle = rotater.angle + 45
}
width: 500; height: 200
color: "lightgray"
Rectangle {
id: rotater
property real angle : 0
x: 240
width: 100; height: 10
color: "black"
y: 95
transform: Rotation {
origin.x: 10; origin.y: 5
angle: rotater.angle
Behavior on angle {
SpringAnimation {
spring: 1.4
damping: .05
}
}
}
}
}
examples/declarative/signals/qmltopy1/ 0000775 0000000 0000000 00000000000 13766170131 0020412 5 ustar 00root root 0000000 0000000 examples/declarative/signals/qmltopy1/main.py 0000664 0000000 0000000 00000006025 13766170131 0021713 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QObject, QUrl, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
class Console(QObject):
"""Output stuff on the console."""
@Slot(str)
@Slot('double')
def output(self, s):
print(s)
@Slot(str)
def outputStr(self, s):
print(s)
@Slot('double')
def outputFloat(self, x):
print(x)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
# Instantiate the Python object.
con = Console()
# Expose the object to QML.
context = view.rootContext()
context.setContextProperty("con", con)
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/signals/qmltopy1/qmltopy1.pyproject 0000664 0000000 0000000 00000000051 13766170131 0024135 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/signals/qmltopy1/view.qml 0000664 0000000 0000000 00000006043 13766170131 0022102 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Rectangle {
id: page
width: 500; height: 200
color: "lightgray"
Text {
id: helloText
text: "Hello world!"
anchors.horizontalCenter: page.horizontalCenter
y: 30
font.pointSize: 24; font.bold: true
}
Rectangle {
id: button
width: 150; height: 40
color: "darkgray"
anchors.horizontalCenter: page.horizontalCenter
y: 120
MouseArea {
id: buttonMouseArea
objectName: "buttonMouseArea"
anchors.fill: parent
onClicked: {
// once the "con" context has been declared,
// slots can be called like functions
con.outputFloat(123)
con.outputStr("foobar")
con.output(helloText.x)
con.output(helloText.text)
}
}
Text {
id: buttonText
text: "Press me!"
anchors.horizontalCenter: button.horizontalCenter
anchors.verticalCenter: button.verticalCenter
font.pointSize: 16
}
}
}
examples/declarative/signals/qmltopy2/ 0000775 0000000 0000000 00000000000 13766170131 0020413 5 ustar 00root root 0000000 0000000 examples/declarative/signals/qmltopy2/main.py 0000664 0000000 0000000 00000006025 13766170131 0021714 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QObject, QUrl, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
class RotateValue(QObject):
def __init__(self):
super(RotateValue,self).__init__()
self.r = 0
# If a slot returns a value, the return value type must be explicitly
# defined in the decorator.
@Slot(result=int)
def val(self):
self.r = self.r + 10
return self.r
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
rotatevalue = RotateValue()
context = view.rootContext()
context.setContextProperty("rotatevalue", rotatevalue)
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/signals/qmltopy2/qmltopy2.pyproject 0000664 0000000 0000000 00000000051 13766170131 0024137 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/signals/qmltopy2/view.qml 0000664 0000000 0000000 00000005507 13766170131 0022107 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Rectangle {
id: page
width: 500; height: 200
color: "lightgray"
Text {
id: helloText
text: "Hello world!"
anchors.horizontalCenter: page.horizontalCenter
y: 30
font.pointSize: 24; font.bold: true
}
Rectangle {
id: button
width: 150; height: 40
color: "darkgray"
anchors.horizontalCenter: page.horizontalCenter
y: 120
MouseArea {
id: buttonMouseArea
objectName: "buttonMouseArea"
anchors.fill: parent
onClicked: {
helloText.rotation = rotatevalue.val()
}
}
Text {
id: buttonText
text: "Press me!"
anchors.horizontalCenter: button.horizontalCenter
anchors.verticalCenter: button.verticalCenter
font.pointSize: 16
}
}
}
examples/declarative/signals/qmltopy3/ 0000775 0000000 0000000 00000000000 13766170131 0020414 5 ustar 00root root 0000000 0000000 examples/declarative/signals/qmltopy3/main.py 0000664 0000000 0000000 00000005422 13766170131 0021715 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
def sayThis(s):
print(s)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
root = view.rootObject()
root.textRotationChanged.connect(sayThis)
root.buttonClicked.connect(lambda: sayThis("clicked button (QML top-level signal)"))
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/signals/qmltopy3/qmltopy3.pyproject 0000664 0000000 0000000 00000000051 13766170131 0024141 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/signals/qmltopy3/view.qml 0000664 0000000 0000000 00000006702 13766170131 0022106 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Rectangle {
id: page
signal buttonClicked
signal textRotationChanged(double rot)
width: 500; height: 200
color: "lightgray"
Text {
id: helloText
text: "Hello world!"
y: 30
x: page.width/2-width/2
font.pointSize: 24; font.bold: true
onRotationChanged: textRotationChanged(rotation)
states: State {
name: "down"; when: buttonMouseArea.pressed === true
PropertyChanges {
target: helloText;
rotation: 180;
y: 100;
}
}
transitions: Transition {
from: ""; to: "down"; reversible: true
ParallelAnimation {
NumberAnimation {
properties: "y,rotation"
duration: 500
easing.type: Easing.InOutQuad
}
}
}
}
Rectangle {
id: button
width: 150; height: 40
color: "darkgray"
anchors.horizontalCenter: page.horizontalCenter
y: 120
MouseArea {
id: buttonMouseArea
objectName: "buttonMouseArea"
anchors.fill: parent
onClicked: {
buttonClicked()
}
}
Text {
id: buttonText
text: "Press me!"
anchors.horizontalCenter: button.horizontalCenter
anchors.verticalCenter: button.verticalCenter
font.pointSize: 16
}
}
}
examples/declarative/signals/qmltopy4/ 0000775 0000000 0000000 00000000000 13766170131 0020415 5 ustar 00root root 0000000 0000000 examples/declarative/signals/qmltopy4/main.py 0000664 0000000 0000000 00000005446 13766170131 0021724 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QObject, QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
def sayThis(s):
print(s)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
root = view.rootObject()
button = root.findChild(QObject, "buttonMouseArea")
button.clicked.connect(lambda: sayThis("clicked button (signal directly connected)"))
view.show()
res = app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)
examples/declarative/signals/qmltopy4/qmltopy4.pyproject 0000664 0000000 0000000 00000000051 13766170131 0024143 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/signals/qmltopy4/view.qml 0000664 0000000 0000000 00000005126 13766170131 0022106 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Rectangle {
id: page
width: 500; height: 200
color: "lightgray"
Rectangle {
id: button
width: 150; height: 40
color: "darkgray"
anchors.horizontalCenter: page.horizontalCenter
anchors.verticalCenter: page.verticalCenter
MouseArea {
id: buttonMouseArea
objectName: "buttonMouseArea"
anchors.fill: parent
}
Text {
id: buttonText
text: "Press me!"
anchors.horizontalCenter: button.horizontalCenter
anchors.verticalCenter: button.verticalCenter
font.pointSize: 16
}
}
}
examples/declarative/textproperties/ 0000775 0000000 0000000 00000000000 13766170131 0020265 5 ustar 00root root 0000000 0000000 examples/declarative/textproperties/main.py 0000664 0000000 0000000 00000007220 13766170131 0021564 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
import sys
from os.path import abspath, dirname, join
from PySide2.QtCore import QObject, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtQuickControls2 import QQuickStyle
class Bridge(QObject):
@Slot(str, result=str)
def getColor(self, s):
if s.lower() == "red":
return "#ef9a9a"
elif s.lower() == "green":
return "#a5d6a7"
elif s.lower() == "blue":
return "#90caf9"
else:
return "white"
@Slot(float, result=int)
def getSize(self, s):
size = int(s * 34)
if size <= 0:
return 1
else:
return size
@Slot(str, result=bool)
def getItalic(self, s):
if s.lower() == "italic":
return True
else:
return False
@Slot(str, result=bool)
def getBold(self, s):
if s.lower() == "bold":
return True
else:
return False
@Slot(str, result=bool)
def getUnderline(self, s):
if s.lower() == "underline":
return True
else:
return False
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
QQuickStyle.setStyle("Material")
engine = QQmlApplicationEngine()
# Instance of the Python object
bridge = Bridge()
# Expose the Python object to QML
context = engine.rootContext()
context.setContextProperty("con", bridge)
# Get the path of the current directory, and then add the name
# of the QML file, to load it.
qmlFile = join(dirname(__file__), 'view.qml')
engine.load(abspath(qmlFile))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
examples/declarative/textproperties/textproperties.pyproject 0000664 0000000 0000000 00000000051 13766170131 0025323 0 ustar 00root root 0000000 0000000 {
"files": ["main.py", "view.qml"]
}
examples/declarative/textproperties/view.qml 0000664 0000000 0000000 00000015222 13766170131 0021754 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.11
import QtQuick.Controls 2.1
import QtQuick.Window 2.1
import QtQuick.Controls.Material 2.1
ApplicationWindow {
id: page
width: 800
height: 400
visible: true
Material.theme: Material.Dark
Material.accent: Material.Red
GridLayout {
id: grid
columns: 2
rows: 3
ColumnLayout {
spacing: 2
Layout.columnSpan: 1
Layout.preferredWidth: 400
Text {
id: leftlabel
Layout.alignment: Qt.AlignHCenter
color: "white"
font.pointSize: 16
text: "Qt for Python"
Layout.preferredHeight: 100
Material.accent: Material.Green
}
RadioButton {
id: italic
Layout.alignment: Qt.AlignLeft
text: "Italic"
onToggled: {
leftlabel.font.italic = con.getItalic(italic.text)
leftlabel.font.bold = con.getBold(italic.text)
leftlabel.font.underline = con.getUnderline(italic.text)
}
}
RadioButton {
id: bold
Layout.alignment: Qt.AlignLeft
text: "Bold"
onToggled: {
leftlabel.font.italic = con.getItalic(bold.text)
leftlabel.font.bold = con.getBold(bold.text)
leftlabel.font.underline = con.getUnderline(bold.text)
}
}
RadioButton {
id: underline
Layout.alignment: Qt.AlignLeft
text: "Underline"
onToggled: {
leftlabel.font.italic = con.getItalic(underline.text)
leftlabel.font.bold = con.getBold(underline.text)
leftlabel.font.underline = con.getUnderline(underline.text)
}
}
RadioButton {
id: noneradio
Layout.alignment: Qt.AlignLeft
text: "None"
checked: true
onToggled: {
leftlabel.font.italic = con.getItalic(noneradio.text)
leftlabel.font.bold = con.getBold(noneradio.text)
leftlabel.font.underline = con.getUnderline(noneradio.text)
}
}
}
ColumnLayout {
id: rightcolumn
spacing: 2
Layout.columnSpan: 1
Layout.preferredWidth: 400
Layout.preferredHeight: 400
Layout.fillWidth: true
RowLayout {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Button {
id: red
text: "Red"
highlighted: true
Material.accent: Material.Red
onClicked: {
leftlabel.color = con.getColor(red.text)
}
}
Button {
id: green
text: "Green"
highlighted: true
Material.accent: Material.Green
onClicked: {
leftlabel.color = con.getColor(green.text)
}
}
Button {
id: blue
text: "Blue"
highlighted: true
Material.accent: Material.Blue
onClicked: {
leftlabel.color = con.getColor(blue.text)
}
}
Button {
id: nonebutton
text: "None"
highlighted: true
Material.accent: Material.BlueGrey
onClicked: {
leftlabel.color = con.getColor(nonebutton.text)
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Text {
id: rightlabel
color: "white"
Layout.alignment: Qt.AlignLeft
text: "Font size"
Material.accent: Material.White
}
Slider {
width: rightcolumn.width*0.6
Layout.alignment: Qt.AlignRight
id: slider
value: 0.5
onValueChanged: {
leftlabel.font.pointSize = con.getSize(value)
}
}
}
}
}
}
examples/declarative/usingmodel.py 0000664 0000000 0000000 00000007161 13766170131 0017711 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
from __future__ import print_function
import os
import sys
from PySide2.QtCore import QAbstractListModel, Qt, QUrl, QByteArray
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
class PersonModel (QAbstractListModel):
MyRole = Qt.UserRole + 1
def __init__(self, parent = None):
QAbstractListModel.__init__(self, parent)
self._data = []
def roleNames(self):
roles = {
PersonModel.MyRole : QByteArray(b'modelData'),
Qt.DisplayRole : QByteArray(b'display')
}
return roles
def rowCount(self, index):
return len(self._data)
def data(self, index, role):
d = self._data[index.row()]
if role == Qt.DisplayRole:
return d['name']
elif role == Qt.DecorationRole:
return Qt.black
elif role == PersonModel.MyRole:
return d['myrole']
return None
def populate(self):
self._data.append({'name':'Qt', 'myrole':'role1'})
self._data.append({'name':'PySide', 'myrole':'role2'})
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
myModel = PersonModel()
myModel.populate()
view.rootContext().setContextProperty("myModel", myModel)
qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
app.exec_()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
examples/declarative/view.qml 0000664 0000000 0000000 00000004741 13766170131 0016657 0 ustar 00root root 0000000 0000000 /****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt for Python examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
ListView {
width: 100
height: 100
anchors.fill: parent
model: myModel
delegate: Component {
Rectangle {
height: 25
width: 100
Text {
function displayText() {
var result = ""
if (typeof display !== "undefined")
result = display + ": "
result += modelData
return result
}
text: displayText()
}
}
}
}
examples/examples.pyproject 0000664 0000000 0000000 00000012255 13766170131 0016465 0 ustar 00root root 0000000 0000000 {
"files": ["charts/memoryusage.py",
"corelib/threads/mandelbrot.py",
"corelib/tools/codecs/codecs.py",
"corelib/tools/regexp.py",
"corelib/tools/settingseditor/settingseditor.py",
"declarative/extending/chapter1-basics/basics.py",
"declarative/extending/chapter2-methods/methods.py",
"declarative/extending/chapter3-bindings/bindings.py",
"declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py",
"declarative/extending/chapter5-listproperties/listproperties.py",
"declarative/scrolling.py",
"declarative/signals/pytoqml1/main.py",
"declarative/signals/qmltopy1/main.py",
"declarative/signals/qmltopy2/main.py",
"declarative/signals/qmltopy3/main.py",
"declarative/signals/qmltopy4/main.py",
"declarative/usingmodel.py",
"installer_test/hello.py",
"macextras/macpasteboardmime.py",
"multimedia/audiooutput.py",
"multimedia/camera.py",
"multimedia/player.py",
"network/blockingfortuneclient.py",
"network/fortuneclient.py",
"network/fortuneserver.py",
"network/threadedfortuneserver.py",
"opengl/2dpainting.py",
"opengl/grabber.py",
"opengl/hellogl.py",
"opengl/overpainting.py",
"opengl/samplebuffers.py",
"opengl/textures/textures.py",
"script/helloscript.py",
"texttospeech/texttospeech.py",
"tutorial/t1.py",
"tutorial/t10.py",
"tutorial/t11.py",
"tutorial/t12.py",
"tutorial/t13.py",
"tutorial/t14.py",
"tutorial/t2.py",
"tutorial/t3.py",
"tutorial/t4.py",
"tutorial/t5.py",
"tutorial/t6.py",
"tutorial/t7.py",
"tutorial/t8.py",
"tutorial/t9.py",
"webenginewidgets/simplebrowser.py",
"widgets/animation/animatedtiles/animatedtiles.py",
"widgets/animation/appchooser/appchooser.py",
"widgets/animation/easing/easing.py",
"widgets/animation/states/states.py",
"widgets/dialogs/classwizard/classwizard.py",
"widgets/dialogs/extension.py",
"widgets/dialogs/findfiles.py",
"widgets/dialogs/standarddialogs.py",
"widgets/dialogs/trivialwizard.py",
"widgets/draganddrop/draggabletext/draggabletext.py",
"widgets/effects/lighting.py",
"widgets/graphicsview/anchorlayout.py",
"widgets/graphicsview/collidingmice/collidingmice.py",
"widgets/graphicsview/diagramscene/diagramscene.py",
"widgets/graphicsview/dragdroprobot/dragdroprobot.py",
"widgets/graphicsview/elasticnodes.py",
"widgets/itemviews/addressbook/adddialogwidget.py",
"widgets/itemviews/addressbook/addressbook.py",
"widgets/itemviews/addressbook/addresswidget.py",
"widgets/itemviews/addressbook/newaddresstab.py",
"widgets/itemviews/addressbook/tablemodel.py",
"widgets/itemviews/basicsortfiltermodel.py",
"widgets/itemviews/fetchmore.py",
"widgets/itemviews/stardelegate/stardelegate.py",
"widgets/itemviews/stardelegate/stareditor.py",
"widgets/itemviews/stardelegate/starrating.py",
"widgets/layouts/basiclayouts.py",
"widgets/layouts/dynamiclayouts.py",
"widgets/layouts/flowlayout.py",
"widgets/mainwindows/application/application.py",
"widgets/mainwindows/dockwidgets/dockwidgets.py",
"widgets/mainwindows/mdi/mdi.py",
"widgets/painting/basicdrawing/basicdrawing.py",
"widgets/painting/concentriccircles.py",
"widgets/richtext/orderform.py",
"widgets/richtext/syntaxhighlighter.py",
"widgets/richtext/syntaxhighlighter/syntaxhighlighter.py",
"widgets/richtext/textobject/textobject.py",
"widgets/state-machine/eventtrans.py",
"widgets/state-machine/factstates.py",
"widgets/state-machine/pingpong.py",
"widgets/state-machine/rogue.py",
"widgets/state-machine/trafficlight.py",
"widgets/state-machine/twowaybutton.py",
"widgets/tutorials/addressbook/part1.py",
"widgets/tutorials/addressbook/part2.py",
"widgets/tutorials/addressbook/part3.py",
"widgets/tutorials/addressbook/part4.py",
"widgets/tutorials/addressbook/part5.py",
"widgets/tutorials/addressbook/part6.py",
"widgets/tutorials/addressbook/part7.py",
"widgets/widgets/hellogl_openglwidget_legacy.py",
"widgets/widgets/tetrix.py",
"xml/dombookmarks/dombookmarks.py",
"xmlpatterns/schema/schema.py"]
}
examples/external/ 0000775 0000000 0000000 00000000000 13766170131 0014523 5 ustar 00root root 0000000 0000000 examples/external/matplotlib/ 0000775 0000000 0000000 00000000000 13766170131 0016672 5 ustar 00root root 0000000 0000000 examples/external/matplotlib/requirements.txt 0000664 0000000 0000000 00000000013 13766170131 0022150 0 ustar 00root root 0000000 0000000 matplotlib
examples/external/matplotlib/widget_3dplot.py 0000664 0000000 0000000 00000022217 13766170131 0022020 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
import sys
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import axes3d
from PySide2.QtCore import Qt, Slot
from PySide2.QtGui import QKeySequence
from PySide2.QtWidgets import (QAction, QApplication, QComboBox, QHBoxLayout,
QHeaderView, QLabel, QMainWindow, QSlider,
QTableWidget, QTableWidgetItem, QVBoxLayout,
QWidget)
"""This example implements the interaction between Qt Widgets and a 3D
matplotlib plot"""
class ApplicationWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.column_names = ["Column A", "Column B", "Column C"]
# Central widget
self._main = QWidget()
self.setCentralWidget(self._main)
# Main menu bar
self.menu = self.menuBar()
self.menu_file = self.menu.addMenu("File")
exit = QAction("Exit", self, triggered=qApp.quit)
self.menu_file.addAction(exit)
self.menu_about = self.menu.addMenu("&About")
about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents),
triggered=qApp.aboutQt)
self.menu_about.addAction(about)
# Figure (Left)
self.fig = Figure(figsize=(5, 3))
self.canvas = FigureCanvas(self.fig)
# Sliders (Left)
self.slider_azim = QSlider(minimum=0, maximum=360, orientation=Qt.Horizontal)
self.slider_elev = QSlider(minimum=0, maximum=360, orientation=Qt.Horizontal)
self.slider_azim_layout = QHBoxLayout()
self.slider_azim_layout.addWidget(QLabel("{}".format(self.slider_azim.minimum())))
self.slider_azim_layout.addWidget(self.slider_azim)
self.slider_azim_layout.addWidget(QLabel("{}".format(self.slider_azim.maximum())))
self.slider_elev_layout = QHBoxLayout()
self.slider_elev_layout.addWidget(QLabel("{}".format(self.slider_elev.minimum())))
self.slider_elev_layout.addWidget(self.slider_elev)
self.slider_elev_layout.addWidget(QLabel("{}".format(self.slider_elev.maximum())))
# Table (Right)
self.table = QTableWidget()
header = self.table.horizontalHeader()
header.setSectionResizeMode(QHeaderView.Stretch)
# ComboBox (Right)
self.combo = QComboBox()
self.combo.addItems(["Wired", "Surface", "Triangular Surface", "Sphere"])
# Right layout
rlayout = QVBoxLayout()
rlayout.setContentsMargins(1, 1, 1, 1)
rlayout.addWidget(QLabel("Plot type:"))
rlayout.addWidget(self.combo)
rlayout.addWidget(self.table)
# Left layout
llayout = QVBoxLayout()
rlayout.setContentsMargins(1, 1, 1, 1)
llayout.addWidget(self.canvas, 88)
llayout.addWidget(QLabel("Azimuth:"), 1)
llayout.addLayout(self.slider_azim_layout, 5)
llayout.addWidget(QLabel("Elevation:"), 1)
llayout.addLayout(self.slider_elev_layout, 5)
# Main layout
layout = QHBoxLayout(self._main)
layout.addLayout(llayout, 70)
layout.addLayout(rlayout, 30)
# Signal and Slots connections
self.combo.currentTextChanged.connect(self.combo_option)
self.slider_azim.valueChanged.connect(self.rotate_azim)
self.slider_elev.valueChanged.connect(self.rotate_elev)
# Initial setup
self.plot_wire()
self._ax.view_init(30, 30)
self.slider_azim.setValue(30)
self.slider_elev.setValue(30)
self.fig.canvas.mpl_connect("button_release_event", self.on_click)
# Matplotlib slot method
def on_click(self, event):
azim, elev = self._ax.azim, self._ax.elev
self.slider_azim.setValue(azim + 180)
self.slider_elev.setValue(elev + 180)
# Utils methods
def set_table_data(self, X, Y, Z):
for i in range(len(X)):
self.table.setItem(i, 0, QTableWidgetItem("{:.2f}".format(X[i])))
self.table.setItem(i, 1, QTableWidgetItem("{:.2f}".format(Y[i])))
self.table.setItem(i, 2, QTableWidgetItem("{:.2f}".format(Z[i])))
def set_canvas_table_configuration(self, row_count, data):
self.fig.set_canvas(self.canvas)
self._ax = self.canvas.figure.add_subplot(projection="3d")
self._ax.set_xlabel(self.column_names[0])
self._ax.set_ylabel(self.column_names[1])
self._ax.set_zlabel(self.column_names[2])
self.table.setRowCount(row_count)
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(self.column_names)
self.set_table_data(data[0], data[1], data[2])
# Plot methods
def plot_wire(self):
# Data
self.X, self.Y, self.Z = axes3d.get_test_data(0.03)
self.set_canvas_table_configuration(len(self.X[0]), (self.X[0], self.Y[0], self.Z[0]))
self._ax.plot_wireframe(self.X, self.Y, self.Z, rstride=10, cstride=10, cmap="viridis")
self.canvas.draw()
def plot_surface(self):
# Data
self.X, self.Y = np.meshgrid(np.linspace(-6, 6, 30), np.linspace(-6, 6, 30))
self.Z = np.sin(np.sqrt(self.X ** 2 + self.Y ** 2))
self.set_canvas_table_configuration(len(self.X[0]), (self.X[0], self.Y[0], self.Z[0]))
self._ax.plot_surface(self.X, self.Y, self.Z,
rstride=1, cstride=1, cmap="viridis", edgecolor="none")
self.canvas.draw()
def plot_triangular_surface(self):
# Data
radii = np.linspace(0.125, 1.0, 8)
angles = np.linspace(0, 2 * np.pi, 36, endpoint=False)[..., np.newaxis]
self.X = np.append(0, (radii * np.cos(angles)).flatten())
self.Y = np.append(0, (radii * np.sin(angles)).flatten())
self.Z = np.sin(-self.X * self.Y)
self.set_canvas_table_configuration(len(self.X), (self.X, self.Y, self.Z))
self._ax.plot_trisurf(self.X, self.Y, self.Z, linewidth=0.2, antialiased=True)
self.canvas.draw()
def plot_sphere(self):
# Data
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
self.X = 10 * np.outer(np.cos(u), np.sin(v))
self.Y = 10 * np.outer(np.sin(u), np.sin(v))
self.Z = 9 * np.outer(np.ones(np.size(u)), np.cos(v))
self.set_canvas_table_configuration(len(self.X), (self.X[0], self.Y[0], self.Z[0]))
self._ax.plot_surface(self.X, self.Y, self.Z)
self.canvas.draw()
# Slots
@Slot()
def combo_option(self, text):
if text == "Wired":
self.plot_wire()
elif text == "Surface":
self.plot_surface()
elif text == "Triangular Surface":
self.plot_triangular_surface()
elif text == "Sphere":
self.plot_sphere()
@Slot()
def rotate_azim(self, value):
self._ax.view_init(self._ax.elev, value)
self.fig.set_canvas(self.canvas)
self.canvas.draw()
@Slot()
def rotate_elev(self, value):
self._ax.view_init(value, self._ax.azim)
self.fig.set_canvas(self.canvas)
self.canvas.draw()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ApplicationWindow()
w.setFixedSize(1280, 720)
w.show()
app.exec_()
examples/external/opencv/ 0000775 0000000 0000000 00000000000 13766170131 0016015 5 ustar 00root root 0000000 0000000 examples/external/opencv/requirements.txt 0000664 0000000 0000000 00000000016 13766170131 0021276 0 ustar 00root root 0000000 0000000 opencv-python
examples/external/opencv/webcam_pattern_detection.py 0000664 0000000 0000000 00000016474 13766170131 0023434 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
import os
import sys
import time
import cv2
from PySide2.QtCore import Qt, QThread, Signal, Slot
from PySide2.QtGui import QImage, QKeySequence, QPixmap
from PySide2.QtWidgets import (QAction, QApplication, QComboBox, QGroupBox,
QHBoxLayout, QLabel, QMainWindow, QPushButton,
QSizePolicy, QVBoxLayout, QWidget)
"""This example uses the video from a webcam to apply pattern
detection from the OpenCV module. e.g.: face, eyes, body, etc."""
class Thread(QThread):
updateFrame = Signal(QImage)
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.trained_file = None
self.status = True
self.cap = True
def set_file(self, fname):
# The data comes with the 'opencv-python' module
self.trained_file = os.path.join(cv2.data.haarcascades, fname)
def run(self):
self.cap = cv2.VideoCapture(0)
while self.status:
cascade = cv2.CascadeClassifier(self.trained_file)
ret, frame = self.cap.read()
if not ret:
continue
# Reading frame in gray scale to process the pattern
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
detections = cascade.detectMultiScale(gray_frame, scaleFactor=1.1,
minNeighbors=5, minSize=(30, 30))
# Drawing green rectangle around the pattern
for (x, y, w, h) in detections:
pos_ori = (x, y)
pos_end = (x + w, y + h)
color = (0, 255, 0)
cv2.rectangle(frame, pos_ori, pos_end, color, 2)
# Reading the image in RGB to display it
color_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Creating and scaling QImage
h, w, ch = color_frame.shape
img = QImage(color_frame.data, w, h, ch * w, QImage.Format_RGB888)
scaled_img = img.scaled(640, 480, Qt.KeepAspectRatio)
# Emit signal
self.updateFrame.emit(scaled_img)
sys.exit(-1)
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
# Title and dimensions
self.setWindowTitle("Patterns detection")
self.setGeometry(0, 0, 800, 500)
# Main menu bar
self.menu = self.menuBar()
self.menu_file = self.menu.addMenu("File")
exit = QAction("Exit", self, triggered=qApp.quit)
self.menu_file.addAction(exit)
self.menu_about = self.menu.addMenu("&About")
about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents),
triggered=qApp.aboutQt)
self.menu_about.addAction(about)
# Create a label for the display camera
self.label = QLabel(self)
self.label.setFixedSize(640, 480)
# Thread in charge of updating the image
self.th = Thread(self)
self.th.finished.connect(self.close)
self.th.updateFrame.connect(self.setImage)
# Model group
self.group_model = QGroupBox("Trained model")
self.group_model.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
model_layout = QHBoxLayout()
self.combobox = QComboBox()
for xml_file in os.listdir(cv2.data.haarcascades):
if xml_file.endswith(".xml"):
self.combobox.addItem(xml_file)
model_layout.addWidget(QLabel("File:"), 10)
model_layout.addWidget(self.combobox, 90)
self.group_model.setLayout(model_layout)
# Buttons layout
buttons_layout = QHBoxLayout()
self.button1 = QPushButton("Start")
self.button2 = QPushButton("Stop/Close")
self.button1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.button2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
buttons_layout.addWidget(self.button2)
buttons_layout.addWidget(self.button1)
right_layout = QHBoxLayout()
right_layout.addWidget(self.group_model, 1)
right_layout.addLayout(buttons_layout, 1)
# Main layout
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addLayout(right_layout)
# Central widget
widget = QWidget(self)
widget.setLayout(layout)
self.setCentralWidget(widget)
# Connections
self.button1.clicked.connect(self.start)
self.button2.clicked.connect(self.kill_thread)
self.button2.setEnabled(False)
self.combobox.currentTextChanged.connect(self.set_model)
@Slot()
def set_model(self, text):
self.th.set_file(text)
@Slot()
def kill_thread(self):
print("Finishing...")
self.button2.setEnabled(False)
self.button1.setEnabled(True)
self.th.cap.release()
cv2.destroyAllWindows()
self.status = False
self.th.terminate()
# Give time for the thread to finish
time.sleep(1)
@Slot()
def start(self):
print("Starting...")
self.button2.setEnabled(True)
self.button1.setEnabled(False)
self.th.set_file(self.combobox.currentText())
self.th.start()
@Slot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
if __name__ == "__main__":
app = QApplication()
w = Window()
w.show()
sys.exit(app.exec_())
examples/external/scikit/ 0000775 0000000 0000000 00000000000 13766170131 0016011 5 ustar 00root root 0000000 0000000 examples/external/scikit/requirements.txt 0000664 0000000 0000000 00000000015 13766170131 0021271 0 ustar 00root root 0000000 0000000 scikit-image
examples/external/scikit/staining_colors_separation.py 0000664 0000000 0000000 00000016066 13766170131 0024016 0 ustar 00root root 0000000 0000000 #############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
import sys
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.figure import Figure
from PySide2.QtCore import Qt, Slot
from PySide2.QtGui import QKeySequence
from PySide2.QtWidgets import (QAction, QApplication, QHBoxLayout, QLabel,
QMainWindow, QPushButton, QSizePolicy,
QVBoxLayout, QWidget)
from skimage import data
from skimage.color import rgb2hed
from skimage.exposure import rescale_intensity
class ApplicationWindow(QMainWindow):
"""
Example based on the example by 'scikit-image' gallery:
"Immunohistochemical staining colors separation"
https://scikit-image.org/docs/stable/auto_examples/color_exposure/plot_ihc_color_separation.html
"""
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self._main = QWidget()
self.setCentralWidget(self._main)
# Main menu bar
self.menu = self.menuBar()
self.menu_file = self.menu.addMenu("File")
exit = QAction("Exit", self, triggered=qApp.quit)
self.menu_file.addAction(exit)
self.menu_about = self.menu.addMenu("&About")
about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents),
triggered=qApp.aboutQt)
self.menu_about.addAction(about)
# Create an artificial color close to the original one
self.ihc_rgb = data.immunohistochemistry()
self.ihc_hed = rgb2hed(self.ihc_rgb)
main_layout = QVBoxLayout(self._main)
plot_layout = QHBoxLayout()
button_layout = QHBoxLayout()
label_layout = QHBoxLayout()
self.canvas1 = FigureCanvas(Figure(figsize=(5, 5)))
self.canvas2 = FigureCanvas(Figure(figsize=(5, 5)))
self._ax1 = self.canvas1.figure.subplots()
self._ax2 = self.canvas2.figure.subplots()
self._ax1.imshow(self.ihc_rgb)
plot_layout.addWidget(self.canvas1)
plot_layout.addWidget(self.canvas2)
self.button1 = QPushButton("Hematoxylin")
self.button2 = QPushButton("Eosin")
self.button3 = QPushButton("DAB")
self.button4 = QPushButton("Fluorescence")
self.button1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.button2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.button3.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.button4.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.button1.clicked.connect(self.plot_hematoxylin)
self.button2.clicked.connect(self.plot_eosin)
self.button3.clicked.connect(self.plot_dab)
self.button4.clicked.connect(self.plot_final)
self.label1 = QLabel("Original", alignment=Qt.AlignCenter)
self.label2 = QLabel("", alignment=Qt.AlignCenter)
font = self.label1.font()
font.setPointSize(16)
self.label1.setFont(font)
self.label2.setFont(font)
label_layout.addWidget(self.label1)
label_layout.addWidget(self.label2)
button_layout.addWidget(self.button1)
button_layout.addWidget(self.button2)
button_layout.addWidget(self.button3)
button_layout.addWidget(self.button4)
main_layout.addLayout(label_layout, 2)
main_layout.addLayout(plot_layout, 88)
main_layout.addLayout(button_layout, 10)
# Default image
self.plot_hematoxylin()
def set_buttons_state(self, states):
self.button1.setEnabled(states[0])
self.button2.setEnabled(states[1])
self.button3.setEnabled(states[2])
self.button4.setEnabled(states[3])
@Slot()
def plot_hematoxylin(self):
cmap_hema = LinearSegmentedColormap.from_list("mycmap", ["white", "navy"])
self._ax2.imshow(self.ihc_hed[:, :, 0], cmap=cmap_hema)
self.canvas2.draw()
self.label2.setText("Hematoxylin")
self.set_buttons_state((False, True, True, True))
@Slot()
def plot_eosin(self):
cmap_eosin = LinearSegmentedColormap.from_list("mycmap", ["darkviolet", "white"])
self._ax2.imshow(self.ihc_hed[:, :, 1], cmap=cmap_eosin)
self.canvas2.draw()
self.label2.setText("Eosin")
self.set_buttons_state((True, False, True, True))
@Slot()
def plot_dab(self):
cmap_dab = LinearSegmentedColormap.from_list("mycmap", ["white", "saddlebrown"])
self._ax2.imshow(self.ihc_hed[:, :, 2], cmap=cmap_dab)
self.canvas2.draw()
self.label2.setText("DAB")
self.set_buttons_state((True, True, False, True))
@Slot()
def plot_final(self):
h = rescale_intensity(self.ihc_hed[:, :, 0], out_range=(0, 1))
d = rescale_intensity(self.ihc_hed[:, :, 2], out_range=(0, 1))
zdh = np.dstack((np.zeros_like(h), d, h))
self._ax2.imshow(zdh)
self.canvas2.draw()
self.label2.setText("Stain separated image")
self.set_buttons_state((True, True, True, False))
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ApplicationWindow()
w.show()
app.exec_()
examples/installer_test/ 0000775 0000000 0000000 00000000000 13766170131 0015735 5 ustar 00root root 0000000 0000000 examples/installer_test/hello.py 0000664 0000000 0000000 00000007457 13766170131 0017427 0 ustar 00root root 0000000 0000000 # This Python file uses the following encoding: utf-8
# It has been edited by fix-complaints.py .
#############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""
hello.py
--------
This simple script shows a label with changing "Hello World" messages.
It can be used directly as a script, but we use it also to automatically
test PyInstaller. See testing/wheel_tester.py .
When used with PyInstaller, it automatically stops its execution after
2 seconds.
"""
from __future__ import print_function
import sys
import random
import platform
import time
from PySide2.QtWidgets import (QApplication, QLabel, QPushButton,
QVBoxLayout, QWidget)
from PySide2.QtCore import Slot, Qt, QTimer
class MyWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.hello = ["Hallo Welt", "你好,世界", "Hei maailma",
"Hola Mundo", "Привет мир"]
self.button = QPushButton("Click me!")
self.text = QLabel("Hello World embedded={}".format(sys.pyside_uses_embedding))
self.text.setAlignment(Qt.AlignCenter)
self.layout = QVBoxLayout()
self.layout.addWidget(self.text)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
# Connecting the signal
self.button.clicked.connect(self.magic)
@Slot()
def magic(self):
self.text.setText(random.choice(self.hello))
if __name__ == "__main__":
print("Start of hello.py ", time.ctime())
print(" sys.version = {}".format(sys.version.splitlines()[0]))
print(" platform.platform() = {}".format(platform.platform()))
app = QApplication()
widget = MyWidget()
widget.resize(800, 600)
widget.show()
if sys.pyside_uses_embedding:
milliseconds = 2 * 1000 # run 2 second
QTimer.singleShot(milliseconds, app.quit)
retcode = app.exec_()
print("End of hello.py ", time.ctime())
sys.exit(retcode)
examples/installer_test/hello_app.spec 0000664 0000000 0000000 00000007332 13766170131 0020561 0 ustar 00root root 0000000 0000000 # This Python file uses the following encoding: utf-8
# It has been edited by fix-complaints.py .
#############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""
hello_app.spec
This is almost the spec file generated by running PyInstaller.
Just the paths were adjusted and made relative.
As an effect, all the analysis is avoided, and the log file of
wheel_tester.py went down from 775 lines to 278 lines. :-)
"""
block_cipher = None
a = Analysis(['hello.py'],
pathex=['pyinstaller'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
# 2019-04-28
# This hack circumvents a side effect of Python 2.7.16 which leads to a failure
# in 'hook-_tkinter.py'. The error is reported. Until it is fixed, we circumvent
# the problem by this exclude.
# This effect is triggered by installing 'numpy'. It is somewhat special since
# the problem does not show up in Python 3.7 . tkinter would have the same
# problem on Python 3.7, but numpy would not trigger it for some reason.
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='hello_app',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='hello_app')
examples/macextras/ 0000775 0000000 0000000 00000000000 13766170131 0014670 5 ustar 00root root 0000000 0000000 examples/macextras/macextras.pyproject 0000664 0000000 0000000 00000000052 13766170131 0020615 0 ustar 00root root 0000000 0000000 {
"files": ["macpasteboardmime.py"]
}
examples/macextras/macpasteboardmime.py 0000664 0000000 0000000 00000010672 13766170131 0020725 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
import sys
from PySide2 import QtCore, QtWidgets
try:
from PySide2 import QtMacExtras
except ImportError:
app = QtWidgets.QApplication(sys.argv)
messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "QtMacExtras macpasteboardmime",
"This exampe only runs on macOS and QtMacExtras must be installed to run this example.",
QtWidgets.QMessageBox.Close)
messageBox.exec_()
sys.exit(1)
class VCardMime(QtMacExtras.QMacPasteboardMime):
def __init__(self, t = QtMacExtras.QMacPasteboardMime.MIME_ALL):
super(VCardMime, self).__init__(t)
def convertorName(self):
return "VCardMime"
def canConvert(self, mime, flav):
if self.mimeFor(flav) == mime:
return True
else:
return False
def mimeFor(self, flav):
if flav == "public.vcard":
return "application/x-mycompany-VCard"
else:
return ""
def flavorFor(self, mime):
if mime == "application/x-mycompany-VCard":
return "public.vcard"
else:
return ""
def convertToMime(self, mime, data, flav):
all = QtCore.QByteArray()
for i in data:
all += i
return all
def convertFromMime(mime, data, flav):
# Todo: implement!
return []
class TestWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(TestWidget, self).__init__(parent)
self.vcardMime = VCardMime()
self.setAcceptDrops(True)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
self.setLayout(layout)
self.label1.setText("Please drag a \"VCard\" from Contacts application, normally a name in the list, and drop here.")
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
e.accept()
self.contentsDropEvent(e)
def contentsDropEvent(self, e):
if e.mimeData().hasFormat("application/x-mycompany-VCard"):
s = e.mimeData().data( "application/x-mycompany-VCard" )
# s now contains text of vcard
self.label2.setText(str(s))
e.acceptProposedAction()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
QtMacExtras.qRegisterDraggedTypes(["public.vcard"])
wid1 = TestWidget()
wid1.show()
sys.exit(app.exec_())
examples/multimedia/ 0000775 0000000 0000000 00000000000 13766170131 0015033 5 ustar 00root root 0000000 0000000 examples/multimedia/audiooutput.py 0000664 0000000 0000000 00000025377 13766170131 0020005 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the multimedia/audiooutput example from Qt v5.x, originating from PyQt"""
from math import pi, sin
from struct import pack
from PySide2.QtCore import QByteArray, QIODevice, Qt, QTimer, qWarning
from PySide2.QtMultimedia import (QAudio, QAudioDeviceInfo, QAudioFormat,
QAudioOutput)
from PySide2.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLabel,
QMainWindow, QPushButton, QSlider, QVBoxLayout, QWidget)
class Generator(QIODevice):
def __init__(self, format, durationUs, sampleRate, parent):
super(Generator, self).__init__(parent)
self.m_pos = 0
self.m_buffer = QByteArray()
self.generateData(format, durationUs, sampleRate)
def start(self):
self.open(QIODevice.ReadOnly)
def stop(self):
self.m_pos = 0
self.close()
def generateData(self, format, durationUs, sampleRate):
pack_format = ''
if format.sampleSize() == 8:
if format.sampleType() == QAudioFormat.UnSignedInt:
scaler = lambda x: ((1.0 + x) / 2 * 255)
pack_format = 'B'
elif format.sampleType() == QAudioFormat.SignedInt:
scaler = lambda x: x * 127
pack_format = 'b'
elif format.sampleSize() == 16:
if format.sampleType() == QAudioFormat.UnSignedInt:
scaler = lambda x: (1.0 + x) / 2 * 65535
pack_format = 'H'
elif format.sampleType() == QAudioFormat.SignedInt:
scaler = lambda x: x * 32767
pack_format = 'h'
assert(pack_format != '')
channelBytes = format.sampleSize() // 8
sampleBytes = format.channelCount() * channelBytes
length = (format.sampleRate() * format.channelCount() * (format.sampleSize() // 8)) * durationUs // 100000
self.m_buffer.clear()
sampleIndex = 0
factor = 2 * pi * sampleRate / format.sampleRate()
while length != 0:
x = sin((sampleIndex % format.sampleRate()) * factor)
packed = pack(pack_format, int(scaler(x)))
for _ in range(format.channelCount()):
self.m_buffer.append(packed)
length -= channelBytes
sampleIndex += 1
def readData(self, maxlen):
data = QByteArray()
total = 0
while maxlen > total:
chunk = min(self.m_buffer.size() - self.m_pos, maxlen - total)
data.append(self.m_buffer.mid(self.m_pos, chunk))
self.m_pos = (self.m_pos + chunk) % self.m_buffer.size()
total += chunk
return data.data()
def writeData(self, data):
return 0
def bytesAvailable(self):
return self.m_buffer.size() + super(Generator, self).bytesAvailable()
class AudioTest(QMainWindow):
PUSH_MODE_LABEL = "Enable push mode"
PULL_MODE_LABEL = "Enable pull mode"
SUSPEND_LABEL = "Suspend playback"
RESUME_LABEL = "Resume playback"
DurationSeconds = 1
ToneSampleRateHz = 600
DataSampleRateHz = 44100
def __init__(self):
super(AudioTest, self).__init__()
self.m_device = QAudioDeviceInfo.defaultOutputDevice()
self.m_output = None
self.initializeWindow()
self.initializeAudio()
def initializeWindow(self):
layout = QVBoxLayout()
self.m_deviceBox = QComboBox()
self.m_deviceBox.activated[int].connect(self.deviceChanged)
for deviceInfo in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput):
self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo)
layout.addWidget(self.m_deviceBox)
self.m_modeButton = QPushButton()
self.m_modeButton.clicked.connect(self.toggleMode)
self.m_modeButton.setText(self.PUSH_MODE_LABEL)
layout.addWidget(self.m_modeButton)
self.m_suspendResumeButton = QPushButton(
clicked=self.toggleSuspendResume)
self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
layout.addWidget(self.m_suspendResumeButton)
volumeBox = QHBoxLayout()
volumeLabel = QLabel("Volume:")
self.m_volumeSlider = QSlider(Qt.Horizontal, minimum=0, maximum=100,
singleStep=10)
self.m_volumeSlider.valueChanged.connect(self.volumeChanged)
volumeBox.addWidget(volumeLabel)
volumeBox.addWidget(self.m_volumeSlider)
layout.addLayout(volumeBox)
window = QWidget()
window.setLayout(layout)
self.setCentralWidget(window)
def initializeAudio(self):
self.m_pullTimer = QTimer(self)
self.m_pullTimer.timeout.connect(self.pullTimerExpired)
self.m_pullMode = True
self.m_format = QAudioFormat()
self.m_format.setSampleRate(self.DataSampleRateHz)
self.m_format.setChannelCount(1)
self.m_format.setSampleSize(16)
self.m_format.setCodec('audio/pcm')
self.m_format.setByteOrder(QAudioFormat.LittleEndian)
self.m_format.setSampleType(QAudioFormat.SignedInt)
info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice())
if not info.isFormatSupported(self.m_format):
qWarning("Default format not supported - trying to use nearest")
self.m_format = info.nearestFormat(self.m_format)
self.m_generator = Generator(self.m_format,
self.DurationSeconds * 1000000, self.ToneSampleRateHz, self)
self.createAudioOutput()
def createAudioOutput(self):
self.m_audioOutput = QAudioOutput(self.m_device, self.m_format)
self.m_audioOutput.notify.connect(self.notified)
self.m_audioOutput.stateChanged.connect(self.handleStateChanged)
self.m_generator.start()
self.m_audioOutput.start(self.m_generator)
self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100)
def deviceChanged(self, index):
self.m_pullTimer.stop()
self.m_generator.stop()
self.m_audioOutput.stop()
self.m_device = self.m_deviceBox.itemData(index)
self.createAudioOutput()
def volumeChanged(self, value):
if self.m_audioOutput is not None:
self.m_audioOutput.setVolume(value / 100.0)
def notified(self):
qWarning("bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" % (
self.m_audioOutput.bytesFree(),
self.m_audioOutput.elapsedUSecs(),
self.m_audioOutput.processedUSecs()))
def pullTimerExpired(self):
if self.m_audioOutput is not None and self.m_audioOutput.state() != QAudio.StoppedState:
chunks = self.m_audioOutput.bytesFree() // self.m_audioOutput.periodSize()
for _ in range(chunks):
data = self.m_generator.read(self.m_audioOutput.periodSize())
if data is None or len(data) != self.m_audioOutput.periodSize():
break
self.m_output.write(data)
def toggleMode(self):
self.m_pullTimer.stop()
self.m_audioOutput.stop()
if self.m_pullMode:
self.m_modeButton.setText(self.PULL_MODE_LABEL)
self.m_output = self.m_audioOutput.start()
self.m_pullMode = False
self.m_pullTimer.start(20)
else:
self.m_modeButton.setText(self.PUSH_MODE_LABEL)
self.m_pullMode = True
self.m_audioOutput.start(self.m_generator)
self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
def toggleSuspendResume(self):
if self.m_audioOutput.state() == QAudio.SuspendedState:
qWarning("status: Suspended, resume()")
self.m_audioOutput.resume()
self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
elif self.m_audioOutput.state() == QAudio.ActiveState:
qWarning("status: Active, suspend()")
self.m_audioOutput.suspend()
self.m_suspendResumeButton.setText(self.RESUME_LABEL)
elif self.m_audioOutput.state() == QAudio.StoppedState:
qWarning("status: Stopped, resume()")
self.m_audioOutput.resume()
self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
elif self.m_audioOutput.state() == QAudio.IdleState:
qWarning("status: IdleState")
stateMap = {
QAudio.ActiveState: "ActiveState",
QAudio.SuspendedState: "SuspendedState",
QAudio.StoppedState: "StoppedState",
QAudio.IdleState: "IdleState"}
def handleStateChanged(self, state):
qWarning("state = " + self.stateMap.get(state, "Unknown"))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
app.setApplicationName("Audio Output Test")
audio = AudioTest()
audio.show()
sys.exit(app.exec_())
examples/multimedia/camera.py 0000664 0000000 0000000 00000015776 13766170131 0016655 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 Multimedia Camera Example"""
import os, sys
from PySide2.QtCore import QDate, QDir, QStandardPaths, Qt, QUrl
from PySide2.QtGui import QGuiApplication, QDesktopServices, QIcon
from PySide2.QtGui import QImage, QPixmap
from PySide2.QtWidgets import (QAction, QApplication, QHBoxLayout, QLabel,
QMainWindow, QPushButton, QTabWidget, QToolBar, QVBoxLayout, QWidget)
from PySide2.QtMultimedia import QCamera, QCameraImageCapture, QCameraInfo
from PySide2.QtMultimediaWidgets import QCameraViewfinder
class ImageView(QWidget):
def __init__(self, previewImage, fileName):
super(ImageView, self).__init__()
self.fileName = fileName
mainLayout = QVBoxLayout(self)
self.imageLabel = QLabel()
self.imageLabel.setPixmap(QPixmap.fromImage(previewImage))
mainLayout.addWidget(self.imageLabel)
topLayout = QHBoxLayout()
self.fileNameLabel = QLabel(QDir.toNativeSeparators(fileName))
self.fileNameLabel.setTextInteractionFlags(Qt.TextBrowserInteraction)
topLayout.addWidget(self.fileNameLabel)
topLayout.addStretch()
copyButton = QPushButton("Copy")
copyButton.setToolTip("Copy file name to clipboard")
topLayout.addWidget(copyButton)
copyButton.clicked.connect(self.copy)
launchButton = QPushButton("Launch")
launchButton.setToolTip("Launch image viewer")
topLayout.addWidget(launchButton)
launchButton.clicked.connect(self.launch)
mainLayout.addLayout(topLayout)
def copy(self):
QGuiApplication.clipboard().setText(self.fileNameLabel.text())
def launch(self):
QDesktopServices.openUrl(QUrl.fromLocalFile(self.fileName))
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.cameraInfo = QCameraInfo.defaultCamera()
self.camera = QCamera(self.cameraInfo)
self.camera.setCaptureMode(QCamera.CaptureStillImage)
self.imageCapture = QCameraImageCapture(self.camera)
self.imageCapture.imageCaptured.connect(self.imageCaptured)
self.imageCapture.imageSaved.connect(self.imageSaved)
self.currentPreview = QImage()
toolBar = QToolBar()
self.addToolBar(toolBar)
fileMenu = self.menuBar().addMenu("&File")
shutterIcon = QIcon(os.path.join(os.path.dirname(__file__),
"shutter.svg"))
self.takePictureAction = QAction(shutterIcon, "&Take Picture", self,
shortcut="Ctrl+T",
triggered=self.takePicture)
self.takePictureAction.setToolTip("Take Picture")
fileMenu.addAction(self.takePictureAction)
toolBar.addAction(self.takePictureAction)
exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
self, shortcut="Ctrl+Q", triggered=self.close)
fileMenu.addAction(exitAction)
aboutMenu = self.menuBar().addMenu("&About")
aboutQtAction = QAction("About &Qt", self, triggered=qApp.aboutQt)
aboutMenu.addAction(aboutQtAction)
self.tabWidget = QTabWidget()
self.setCentralWidget(self.tabWidget)
self.cameraViewfinder = QCameraViewfinder()
self.camera.setViewfinder(self.cameraViewfinder)
self.tabWidget.addTab(self.cameraViewfinder, "Viewfinder")
if self.camera.status() != QCamera.UnavailableStatus:
name = self.cameraInfo.description()
self.setWindowTitle("PySide2 Camera Example (" + name + ")")
self.statusBar().showMessage("Starting: '" + name + "'", 5000)
self.camera.start()
else:
self.setWindowTitle("PySide2 Camera Example")
self.takePictureAction.setEnabled(False)
self.statusBar().showMessage("Camera unavailable", 5000)
def nextImageFileName(self):
picturesLocation = QStandardPaths.writableLocation(QStandardPaths.PicturesLocation)
dateString = QDate.currentDate().toString("yyyyMMdd")
pattern = picturesLocation + "/pyside2_camera_" + dateString + "_{:03d}.jpg"
n = 1
while True:
result = pattern.format(n)
if not os.path.exists(result):
return result
n = n + 1
return None
def takePicture(self):
self.currentPreview = QImage()
self.camera.searchAndLock()
self.imageCapture.capture(self.nextImageFileName())
self.camera.unlock()
def imageCaptured(self, id, previewImage):
self.currentPreview = previewImage
def imageSaved(self, id, fileName):
index = self.tabWidget.count()
imageView = ImageView(self.currentPreview, fileName)
self.tabWidget.addTab(imageView, "Capture #{}".format(index))
self.tabWidget.setCurrentIndex(index)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
availableGeometry = app.desktop().availableGeometry(mainWin)
mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
mainWin.show()
sys.exit(app.exec_())
examples/multimedia/multimedia.pyproject 0000664 0000000 0000000 00000000076 13766170131 0021131 0 ustar 00root root 0000000 0000000 {
"files": ["player.py", "audiooutput.py", "camera.py"]
}
examples/multimedia/player.py 0000664 0000000 0000000 00000015467 13766170131 0016716 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 Multimedia player example"""
import sys
from PySide2.QtCore import QStandardPaths, Qt
from PySide2.QtGui import QIcon, QKeySequence
from PySide2.QtWidgets import (QAction, QApplication, QDialog, QFileDialog,
QMainWindow, QSlider, QStyle, QToolBar)
from PySide2.QtMultimedia import QMediaPlayer, QMediaPlaylist
from PySide2.QtMultimediaWidgets import QVideoWidget
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.playlist = QMediaPlaylist()
self.player = QMediaPlayer()
toolBar = QToolBar()
self.addToolBar(toolBar)
fileMenu = self.menuBar().addMenu("&File")
openAction = QAction(QIcon.fromTheme("document-open"),
"&Open...", self, shortcut=QKeySequence.Open,
triggered=self.open)
fileMenu.addAction(openAction)
exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
self, shortcut="Ctrl+Q", triggered=self.close)
fileMenu.addAction(exitAction)
playMenu = self.menuBar().addMenu("&Play")
playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
self.playAction = toolBar.addAction(playIcon, "Play")
self.playAction.triggered.connect(self.player.play)
playMenu.addAction(self.playAction)
previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward)
self.previousAction = toolBar.addAction(previousIcon, "Previous")
self.previousAction.triggered.connect(self.previousClicked)
playMenu.addAction(self.previousAction)
pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
self.pauseAction = toolBar.addAction(pauseIcon, "Pause")
self.pauseAction.triggered.connect(self.player.pause)
playMenu.addAction(self.pauseAction)
nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward)
self.nextAction = toolBar.addAction(nextIcon, "Next")
self.nextAction.triggered.connect(self.playlist.next)
playMenu.addAction(self.nextAction)
stopIcon = self.style().standardIcon(QStyle.SP_MediaStop)
self.stopAction = toolBar.addAction(stopIcon, "Stop")
self.stopAction.triggered.connect(self.player.stop)
playMenu.addAction(self.stopAction)
self.volumeSlider = QSlider()
self.volumeSlider.setOrientation(Qt.Horizontal)
self.volumeSlider.setMinimum(0)
self.volumeSlider.setMaximum(100)
self.volumeSlider.setFixedWidth(app.desktop().availableGeometry(self).width() / 10)
self.volumeSlider.setValue(self.player.volume())
self.volumeSlider.setTickInterval(10)
self.volumeSlider.setTickPosition(QSlider.TicksBelow)
self.volumeSlider.setToolTip("Volume")
self.volumeSlider.valueChanged.connect(self.player.setVolume)
toolBar.addWidget(self.volumeSlider)
aboutMenu = self.menuBar().addMenu("&About")
aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
aboutMenu.addAction(aboutQtAct)
self.videoWidget = QVideoWidget()
self.setCentralWidget(self.videoWidget)
self.player.setPlaylist(self.playlist)
self.player.stateChanged.connect(self.updateButtons)
self.player.setVideoOutput(self.videoWidget)
self.updateButtons(self.player.state())
def open(self):
fileDialog = QFileDialog(self)
supportedMimeTypes = QMediaPlayer.supportedMimeTypes()
if not supportedMimeTypes:
supportedMimeTypes.append("video/x-msvideo") # AVI
fileDialog.setMimeTypeFilters(supportedMimeTypes)
moviesLocation = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation)
fileDialog.setDirectory(moviesLocation)
if fileDialog.exec_() == QDialog.Accepted:
self.playlist.addMedia(fileDialog.selectedUrls()[0])
self.player.play()
def previousClicked(self):
# Go to previous track if we are within the first 5 seconds of playback
# Otherwise, seek to the beginning.
if self.player.position() <= 5000:
self.playlist.previous()
else:
player.setPosition(0)
def updateButtons(self, state):
mediaCount = self.playlist.mediaCount()
self.playAction.setEnabled(mediaCount > 0
and state != QMediaPlayer.PlayingState)
self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState)
self.stopAction.setEnabled(state != QMediaPlayer.StoppedState)
self.previousAction.setEnabled(self.player.position() > 0)
self.nextAction.setEnabled(mediaCount > 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
availableGeometry = app.desktop().availableGeometry(mainWin)
mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
mainWin.show()
sys.exit(app.exec_())
examples/multimedia/shutter.svg 0000664 0000000 0000000 00000002676 13766170131 0017265 0 ustar 00root root 0000000 0000000
examples/network/ 0000775 0000000 0000000 00000000000 13766170131 0014372 5 ustar 00root root 0000000 0000000 examples/network/blockingfortuneclient.py 0000664 0000000 0000000 00000020241 13766170131 0021335 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the network/blockingfortunclient example from Qt v5.x, originating from PyQt"""
from PySide2.QtCore import (Signal, QDataStream, QMutex, QMutexLocker,
QThread, QWaitCondition)
from PySide2.QtGui import QIntValidator
from PySide2.QtWidgets import (QApplication, QDialogButtonBox, QGridLayout,
QLabel, QLineEdit, QMessageBox, QPushButton, QWidget)
from PySide2.QtNetwork import (QAbstractSocket, QHostAddress, QNetworkInterface,
QTcpSocket)
class FortuneThread(QThread):
newFortune = Signal(str)
error = Signal(int, str)
def __init__(self, parent=None):
super(FortuneThread, self).__init__(parent)
self.quit = False
self.hostName = ''
self.cond = QWaitCondition()
self.mutex = QMutex()
self.port = 0
def __del__(self):
self.mutex.lock()
self.quit = True
self.cond.wakeOne()
self.mutex.unlock()
self.wait()
def requestNewFortune(self, hostname, port):
locker = QMutexLocker(self.mutex)
self.hostName = hostname
self.port = port
if not self.isRunning():
self.start()
else:
self.cond.wakeOne()
def run(self):
self.mutex.lock()
serverName = self.hostName
serverPort = self.port
self.mutex.unlock()
while not self.quit:
Timeout = 5 * 1000
socket = QTcpSocket()
socket.connectToHost(serverName, serverPort)
if not socket.waitForConnected(Timeout):
self.error.emit(socket.error(), socket.errorString())
return
while socket.bytesAvailable() < 2:
if not socket.waitForReadyRead(Timeout):
self.error.emit(socket.error(), socket.errorString())
return
instr = QDataStream(socket)
instr.setVersion(QDataStream.Qt_4_0)
blockSize = instr.readUInt16()
while socket.bytesAvailable() < blockSize:
if not socket.waitForReadyRead(Timeout):
self.error.emit(socket.error(), socket.errorString())
return
self.mutex.lock()
fortune = instr.readQString()
self.newFortune.emit(fortune)
self.cond.wait(self.mutex)
serverName = self.hostName
serverPort = self.port
self.mutex.unlock()
class BlockingClient(QWidget):
def __init__(self, parent=None):
super(BlockingClient, self).__init__(parent)
self.thread = FortuneThread()
self.currentFortune = ''
hostLabel = QLabel("&Server name:")
portLabel = QLabel("S&erver port:")
for ipAddress in QNetworkInterface.allAddresses():
if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0:
break
else:
ipAddress = QHostAddress(QHostAddress.LocalHost)
ipAddress = ipAddress.toString()
self.hostLineEdit = QLineEdit(ipAddress)
self.portLineEdit = QLineEdit()
self.portLineEdit.setValidator(QIntValidator(1, 65535, self))
hostLabel.setBuddy(self.hostLineEdit)
portLabel.setBuddy(self.portLineEdit)
self.statusLabel = QLabel(
"This example requires that you run the Fortune Server example as well.")
self.statusLabel.setWordWrap(True)
self.getFortuneButton = QPushButton("Get Fortune")
self.getFortuneButton.setDefault(True)
self.getFortuneButton.setEnabled(False)
quitButton = QPushButton("Quit")
buttonBox = QDialogButtonBox()
buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole)
buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole)
self.getFortuneButton.clicked.connect(self.requestNewFortune)
quitButton.clicked.connect(self.close)
self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)
self.portLineEdit.textChanged.connect(self.enableGetFortuneButton)
self.thread.newFortune.connect(self.showFortune)
self.thread.error.connect(self.displayError)
mainLayout = QGridLayout()
mainLayout.addWidget(hostLabel, 0, 0)
mainLayout.addWidget(self.hostLineEdit, 0, 1)
mainLayout.addWidget(portLabel, 1, 0)
mainLayout.addWidget(self.portLineEdit, 1, 1)
mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
mainLayout.addWidget(buttonBox, 3, 0, 1, 2)
self.setLayout(mainLayout)
self.setWindowTitle("Blocking Fortune Client")
self.portLineEdit.setFocus()
def requestNewFortune(self):
self.getFortuneButton.setEnabled(False)
self.thread.requestNewFortune(self.hostLineEdit.text(),
int(self.portLineEdit.text()))
def showFortune(self, nextFortune):
if nextFortune == self.currentFortune:
self.requestNewFortune()
return
self.currentFortune = nextFortune
self.statusLabel.setText(self.currentFortune)
self.getFortuneButton.setEnabled(True)
def displayError(self, socketError, message):
if socketError == QAbstractSocket.HostNotFoundError:
QMessageBox.information(self, "Blocking Fortune Client",
"The host was not found. Please check the host and port "
"settings.")
elif socketError == QAbstractSocket.ConnectionRefusedError:
QMessageBox.information(self, "Blocking Fortune Client",
"The connection was refused by the peer. Make sure the "
"fortune server is running, and check that the host name "
"and port settings are correct.")
else:
QMessageBox.information(self, "Blocking Fortune Client",
"The following error occurred: %s." % message)
self.getFortuneButton.setEnabled(True)
def enableGetFortuneButton(self):
self.getFortuneButton.setEnabled(self.hostLineEdit.text() != '' and
self.portLineEdit.text() != '')
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
client = BlockingClient()
client.show()
sys.exit(app.exec_())
examples/network/fortuneclient.py 0000664 0000000 0000000 00000014721 13766170131 0017632 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the network/fortuneclient example from Qt v5.x"""
from PySide2 import QtCore, QtGui, QtWidgets, QtNetwork
class Client(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Client, self).__init__(parent)
self.blockSize = 0
self.currentFortune = ''
hostLabel = QtWidgets.QLabel("&Server name:")
portLabel = QtWidgets.QLabel("S&erver port:")
self.hostLineEdit = QtWidgets.QLineEdit('Localhost')
self.portLineEdit = QtWidgets.QLineEdit()
self.portLineEdit.setValidator(QtGui.QIntValidator(1, 65535, self))
hostLabel.setBuddy(self.hostLineEdit)
portLabel.setBuddy(self.portLineEdit)
self.statusLabel = QtWidgets.QLabel("This examples requires that you run "
"the Fortune Server example as well.")
self.getFortuneButton = QtWidgets.QPushButton("Get Fortune")
self.getFortuneButton.setDefault(True)
self.getFortuneButton.setEnabled(False)
quitButton = QtWidgets.QPushButton("Quit")
buttonBox = QtWidgets.QDialogButtonBox()
buttonBox.addButton(self.getFortuneButton,
QtWidgets.QDialogButtonBox.ActionRole)
buttonBox.addButton(quitButton, QtWidgets.QDialogButtonBox.RejectRole)
self.tcpSocket = QtNetwork.QTcpSocket(self)
self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)
self.portLineEdit.textChanged.connect(self.enableGetFortuneButton)
self.getFortuneButton.clicked.connect(self.requestNewFortune)
quitButton.clicked.connect(self.close)
self.tcpSocket.readyRead.connect(self.readFortune)
self.tcpSocket.error.connect(self.displayError)
mainLayout = QtWidgets.QGridLayout()
mainLayout.addWidget(hostLabel, 0, 0)
mainLayout.addWidget(self.hostLineEdit, 0, 1)
mainLayout.addWidget(portLabel, 1, 0)
mainLayout.addWidget(self.portLineEdit, 1, 1)
mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
mainLayout.addWidget(buttonBox, 3, 0, 1, 2)
self.setLayout(mainLayout)
self.setWindowTitle("Fortune Client")
self.portLineEdit.setFocus()
def requestNewFortune(self):
self.getFortuneButton.setEnabled(False)
self.blockSize = 0
self.tcpSocket.abort()
self.tcpSocket.connectToHost(self.hostLineEdit.text(),
int(self.portLineEdit.text()))
def readFortune(self):
instr = QtCore.QDataStream(self.tcpSocket)
instr.setVersion(QtCore.QDataStream.Qt_4_0)
if self.blockSize == 0:
if self.tcpSocket.bytesAvailable() < 2:
return
self.blockSize = instr.readUInt16()
if self.tcpSocket.bytesAvailable() < self.blockSize:
return
nextFortune = instr.readString()
try:
# Python v3.
nextFortune = str(nextFortune, encoding='ascii')
except TypeError:
# Python v2.
pass
if nextFortune == self.currentFortune:
QtCore.QTimer.singleShot(0, self.requestNewFortune)
return
self.currentFortune = nextFortune
self.statusLabel.setText(self.currentFortune)
self.getFortuneButton.setEnabled(True)
def displayError(self, socketError):
if socketError == QtNetwork.QAbstractSocket.RemoteHostClosedError:
pass
elif socketError == QtNetwork.QAbstractSocket.HostNotFoundError:
QtWidgets.QMessageBox.information(self, "Fortune Client",
"The host was not found. Please check the host name and "
"port settings.")
elif socketError == QtNetwork.QAbstractSocket.ConnectionRefusedError:
QtWidgets.QMessageBox.information(self, "Fortune Client",
"The connection was refused by the peer. Make sure the "
"fortune server is running, and check that the host name "
"and port settings are correct.")
else:
QtWidgets.QMessageBox.information(self, "Fortune Client",
"The following error occurred: %s." % self.tcpSocket.errorString())
self.getFortuneButton.setEnabled(True)
def enableGetFortuneButton(self):
self.getFortuneButton.setEnabled(bool(self.hostLineEdit.text() and
self.portLineEdit.text()))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
client = Client()
client.show()
sys.exit(client.exec_())
examples/network/fortuneserver.py 0000664 0000000 0000000 00000010740 13766170131 0017657 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the network/fortuneserver example from Qt v5.x"""
import random
from PySide2 import QtCore, QtWidgets, QtNetwork
class Server(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Server, self).__init__(parent)
statusLabel = QtWidgets.QLabel()
quitButton = QtWidgets.QPushButton("Quit")
quitButton.setAutoDefault(False)
self.tcpServer = QtNetwork.QTcpServer(self)
if not self.tcpServer.listen():
QtWidgets.QMessageBox.critical(self, "Fortune Server",
"Unable to start the server: %s." % self.tcpServer.errorString())
self.close()
return
statusLabel.setText("The server is running on port %d.\nRun the "
"Fortune Client example now." % self.tcpServer.serverPort())
self.fortunes = (
"You've been leading a dog's life. Stay off the furniture.",
"You've got to think about tomorrow.",
"You will be surprised by a loud noise.",
"You will feel hungry again in another hour.",
"You might have mail.",
"You cannot kill time without injuring eternity.",
"Computers are not intelligent. They only think they are.")
quitButton.clicked.connect(self.close)
self.tcpServer.newConnection.connect(self.sendFortune)
buttonLayout = QtWidgets.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(quitButton)
buttonLayout.addStretch(1)
mainLayout = QtWidgets.QVBoxLayout()
mainLayout.addWidget(statusLabel)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Fortune Server")
def sendFortune(self):
block = QtCore.QByteArray()
out = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly)
out.setVersion(QtCore.QDataStream.Qt_4_0)
out.writeUInt16(0)
fortune = self.fortunes[random.randint(0, len(self.fortunes) - 1)]
out.writeString(fortune)
out.device().seek(0)
out.writeUInt16(block.size() - 2)
clientConnection = self.tcpServer.nextPendingConnection()
clientConnection.disconnected.connect(clientConnection.deleteLater)
clientConnection.write(block)
clientConnection.disconnectFromHost()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
server = Server()
random.seed(None)
sys.exit(server.exec_())
examples/network/network.pyproject 0000664 0000000 0000000 00000000200 13766170131 0020014 0 ustar 00root root 0000000 0000000 {
"files": ["blockingfortuneclient.py", "fortuneserver.py",
"threadedfortuneserver.py", "fortuneclient.py"]
}
examples/network/threadedfortuneserver.py 0000664 0000000 0000000 00000012754 13766170131 0021367 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the network/threadedfortuneserver example from Qt v5.x, originating from PyQt"""
import random
from PySide2.QtCore import (Signal, QByteArray, QDataStream, QIODevice,
QThread, Qt)
from PySide2.QtWidgets import (QApplication, QDialog, QHBoxLayout, QLabel,
QMessageBox, QPushButton, QVBoxLayout)
from PySide2.QtNetwork import (QHostAddress, QNetworkInterface, QTcpServer,
QTcpSocket)
class FortuneThread(QThread):
error = Signal(QTcpSocket.SocketError)
def __init__(self, socketDescriptor, fortune, parent):
super(FortuneThread, self).__init__(parent)
self.socketDescriptor = socketDescriptor
self.text = fortune
def run(self):
tcpSocket = QTcpSocket()
if not tcpSocket.setSocketDescriptor(self.socketDescriptor):
self.error.emit(tcpSocket.error())
return
block = QByteArray()
outstr = QDataStream(block, QIODevice.WriteOnly)
outstr.setVersion(QDataStream.Qt_4_0)
outstr.writeUInt16(0)
outstr.writeQString(self.text)
outstr.device().seek(0)
outstr.writeUInt16(block.size() - 2)
tcpSocket.write(block)
tcpSocket.disconnectFromHost()
tcpSocket.waitForDisconnected()
class FortuneServer(QTcpServer):
fortunes = (
"You've been leading a dog's life. Stay off the furniture.",
"You've got to think about tomorrow.",
"You will be surprised by a loud noise.",
"You will feel hungry again in another hour.",
"You might have mail.",
"You cannot kill time without injuring eternity.",
"Computers are not intelligent. They only think they are.")
def incomingConnection(self, socketDescriptor):
fortune = self.fortunes[random.randint(0, len(self.fortunes) - 1)]
thread = FortuneThread(socketDescriptor, fortune, self)
thread.finished.connect(thread.deleteLater)
thread.start()
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.server = FortuneServer()
statusLabel = QLabel()
statusLabel.setTextInteractionFlags(Qt.TextBrowserInteraction)
statusLabel.setWordWrap(True)
quitButton = QPushButton("Quit")
quitButton.setAutoDefault(False)
if not self.server.listen():
QMessageBox.critical(self, "Threaded Fortune Server",
"Unable to start the server: %s." % self.server.errorString())
self.close()
return
for ipAddress in QNetworkInterface.allAddresses():
if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0:
break
else:
ipAddress = QHostAddress(QHostAddress.LocalHost)
ipAddress = ipAddress.toString()
statusLabel.setText("The server is running on\n\nIP: %s\nport: %d\n\n"
"Run the Fortune Client example now." % (ipAddress, self.server.serverPort()))
quitButton.clicked.connect(self.close)
buttonLayout = QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(quitButton)
buttonLayout.addStretch(1)
mainLayout = QVBoxLayout()
mainLayout.addWidget(statusLabel)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Threaded Fortune Server")
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = Dialog()
dialog.show()
sys.exit(dialog.exec_())
examples/opengl/ 0000775 0000000 0000000 00000000000 13766170131 0014165 5 ustar 00root root 0000000 0000000 examples/opengl/2dpainting.py 0000664 0000000 0000000 00000013563 13766170131 0016606 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/legacy/2dpainting example from Qt v5.x"""
import sys
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtOpenGL import *
try:
from OpenGL import GL
except ImportError:
app = QApplication(sys.argv)
messageBox = QMessageBox(QMessageBox.Critical, "OpenGL 2dpainting",
"PyOpenGL must be installed to run this example.",
QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class Helper:
def __init__(self):
gradient = QLinearGradient(QPointF(50, -20), QPointF(80, 20))
gradient.setColorAt(0.0, Qt.white)
gradient.setColorAt(1.0, QColor(0xa6, 0xce, 0x39))
self.background = QBrush(QColor(64, 32, 64))
self.circleBrush = QBrush(gradient)
self.circlePen = QPen(Qt.black)
self.circlePen.setWidth(1)
self.textPen = QPen(Qt.white)
self.textFont = QFont()
self.textFont.setPixelSize(50)
def paint(self, painter, event, elapsed):
painter.fillRect(event.rect(), self.background)
painter.translate(100, 100)
painter.save()
painter.setBrush(self.circleBrush)
painter.setPen(self.circlePen)
painter.rotate(elapsed * 0.030)
r = elapsed/1000.0
n = 30
for i in range(n):
painter.rotate(30)
radius = 0 + 120.0*((i+r)/n)
circleRadius = 1 + ((i+r)/n)*20
painter.drawEllipse(QRectF(radius, -circleRadius,
circleRadius*2, circleRadius*2))
painter.restore()
painter.setPen(self.textPen)
painter.setFont(self.textFont)
painter.drawText(QRect(-50, -50, 100, 100), Qt.AlignCenter, "Qt")
class Widget(QWidget):
def __init__(self, helper, parent = None):
QWidget.__init__(self, parent)
self.helper = helper
self.elapsed = 0
self.setFixedSize(200, 200)
def animate(self):
self.elapsed = (self.elapsed + self.sender().interval()) % 1000
self.repaint()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
self.helper.paint(painter, event, self.elapsed)
painter.end()
class GLWidget(QGLWidget):
def __init__(self, helper, parent = None):
QGLWidget.__init__(self, QGLFormat(QGL.SampleBuffers), parent)
self.helper = helper
self.elapsed = 0
self.setFixedSize(200, 200)
def animate(self):
self.elapsed = (self.elapsed + self.sender().interval()) % 1000
self.repaint()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
self.helper.paint(painter, event, self.elapsed)
painter.end()
class Window(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
helper = Helper()
native = Widget(helper, self)
openGL = GLWidget(helper, self)
nativeLabel = QLabel(self.tr("Native"))
nativeLabel.setAlignment(Qt.AlignHCenter)
openGLLabel = QLabel(self.tr("OpenGL"))
openGLLabel.setAlignment(Qt.AlignHCenter)
layout = QGridLayout()
layout.addWidget(native, 0, 0)
layout.addWidget(openGL, 0, 1)
layout.addWidget(nativeLabel, 1, 0)
layout.addWidget(openGLLabel, 1, 1)
self.setLayout(layout)
timer = QTimer(self)
self.connect(timer, SIGNAL("timeout()"), native.animate)
self.connect(timer, SIGNAL("timeout()"), openGL.animate)
timer.start(50)
self.setWindowTitle(self.tr("2D Painting on Native and OpenGL Widgets"))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
examples/opengl/contextinfo.py 0000664 0000000 0000000 00000026032 13766170131 0017102 0 ustar 00root root 0000000 0000000
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the opengl/contextinfo example from Qt v5.x"""
from argparse import ArgumentParser, RawTextHelpFormatter
import numpy
import sys
from textwrap import dedent
from PySide2.QtCore import QCoreApplication, QLibraryInfo, QSize, QTimer, Qt
from PySide2.QtGui import (QMatrix4x4, QOpenGLBuffer, QOpenGLContext, QOpenGLShader,
QOpenGLShaderProgram, QOpenGLVertexArrayObject, QSurfaceFormat, QWindow)
from PySide2.QtWidgets import (QApplication, QHBoxLayout, QMessageBox, QPlainTextEdit,
QWidget)
from PySide2.support import VoidPtr
try:
from OpenGL import GL
except ImportError:
app = QApplication(sys.argv)
messageBox = QMessageBox(QMessageBox.Critical, "ContextInfo",
"PyOpenGL must be installed to run this example.",
QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
vertexShaderSource110 = dedent("""
// version 110
attribute highp vec4 posAttr;
attribute lowp vec4 colAttr;
varying lowp vec4 col;
uniform highp mat4 matrix;
void main() {
col = colAttr;
gl_Position = matrix * posAttr;
}
""")
fragmentShaderSource110 = dedent("""
// version 110
varying lowp vec4 col;
void main() {
gl_FragColor = col;
}
""")
vertexShaderSource = dedent("""
// version 150
in vec4 posAttr;
in vec4 colAttr;
out vec4 col;
uniform mat4 matrix;
void main() {
col = colAttr;
gl_Position = matrix * posAttr;
}
""")
fragmentShaderSource = dedent("""
// version 150
in vec4 col;
out vec4 fragColor;
void main() {
fragColor = col;
}
""")
vertices = numpy.array([0, 0.707, -0.5, -0.5, 0.5, -0.5], dtype = numpy.float32)
colors = numpy.array([1, 0, 0, 0, 1, 0, 0, 0, 1], dtype = numpy.float32)
def print_surface_format(surface_format):
profile_name = 'core' if surface_format.profile() == QSurfaceFormat.CoreProfile else 'compatibility'
return "{} version {}.{}".format(profile_name,
surface_format.majorVersion(), surface_format.minorVersion())
class RenderWindow(QWindow):
def __init__(self, format):
super(RenderWindow, self).__init__()
self.setSurfaceType(QWindow.OpenGLSurface)
self.setFormat(format)
self.context = QOpenGLContext(self)
self.context.setFormat(self.requestedFormat())
if not self.context.create():
raise Exception("Unable to create GL context")
self.program = None
self.timer = None
self.angle = 0
def initGl(self):
self.program = QOpenGLShaderProgram(self)
self.vao = QOpenGLVertexArrayObject()
self.vbo = QOpenGLBuffer()
format = self.context.format()
useNewStyleShader = format.profile() == QSurfaceFormat.CoreProfile
# Try to handle 3.0 & 3.1 that do not have the core/compatibility profile
# concept 3.2+ has. This may still fail since version 150 (3.2) is
# specified in the sources but it's worth a try.
if (format.renderableType() == QSurfaceFormat.OpenGL and format.majorVersion() == 3
and format.minorVersion() <= 1):
useNewStyleShader = not format.testOption(QSurfaceFormat.DeprecatedFunctions)
vertexShader = vertexShaderSource if useNewStyleShader else vertexShaderSource110
fragmentShader = fragmentShaderSource if useNewStyleShader else fragmentShaderSource110
if not self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertexShader):
raise Exception("Vertex shader could not be added: {} ({})".format(self.program.log(), vertexShader))
if not self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragmentShader):
raise Exception("Fragment shader could not be added: {} ({})".format(self.program.log(), fragmentShader))
if not self.program.link():
raise Exception("Could not link shaders: {}".format(self.program.log()))
self.posAttr = self.program.attributeLocation("posAttr")
self.colAttr = self.program.attributeLocation("colAttr")
self.matrixUniform = self.program.uniformLocation("matrix")
self.vbo.create()
self.vbo.bind()
self.verticesData = vertices.tobytes()
self.colorsData = colors.tobytes()
verticesSize = 4 * vertices.size
colorsSize = 4 * colors.size
self.vbo.allocate(VoidPtr(self.verticesData), verticesSize + colorsSize)
self.vbo.write(verticesSize, VoidPtr(self.colorsData), colorsSize)
self.vbo.release()
vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
if self.vao.isCreated(): # have VAO support, use it
self.setupVertexAttribs()
def setupVertexAttribs(self):
self.vbo.bind()
self.program.setAttributeBuffer(self.posAttr, GL.GL_FLOAT, 0, 2)
self.program.setAttributeBuffer(self.colAttr, GL.GL_FLOAT, 4 * vertices.size, 3)
self.program.enableAttributeArray(self.posAttr)
self.program.enableAttributeArray(self.colAttr)
self.vbo.release()
def exposeEvent(self, event):
if self.isExposed():
self.render()
if self.timer is None:
self.timer = QTimer(self)
self.timer.timeout.connect(self.slotTimer)
if not self.timer.isActive():
self.timer.start(10)
else:
if self.timer and self.timer.isActive():
self.timer.stop()
def render(self):
if not self.context.makeCurrent(self):
raise Exception("makeCurrent() failed")
functions = self.context.functions()
if self.program is None:
functions.glEnable(GL.GL_DEPTH_TEST)
functions.glClearColor(0, 0, 0, 1)
self.initGl()
retinaScale = self.devicePixelRatio()
functions.glViewport(0, 0, self.width() * retinaScale,
self.height() * retinaScale)
functions.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
self.program.bind()
matrix = QMatrix4x4()
matrix.perspective(60, 4 / 3, 0.1, 100)
matrix.translate(0, 0, -2)
matrix.rotate(self.angle, 0, 1, 0)
self.program.setUniformValue(self.matrixUniform, matrix)
if self.vao.isCreated():
self.vao.bind()
else: # no VAO support, set the vertex attribute arrays now
self.setupVertexAttribs()
functions.glDrawArrays(GL.GL_TRIANGLES, 0, 3)
self.vao.release()
self.program.release()
# swapInterval is 1 by default which means that swapBuffers() will (hopefully) block
# and wait for vsync.
self.context.swapBuffers(self)
self.context.doneCurrent()
def slotTimer(self):
self.render()
self.angle += 1
def glInfo(self):
if not self.context.makeCurrent(self):
raise Exception("makeCurrent() failed")
functions = self.context.functions()
text = """Vendor: {}\nRenderer: {}\nVersion: {}\nShading language: {}
\nContext Format: {}\n\nSurface Format: {}""".format(
functions.glGetString(GL.GL_VENDOR), functions.glGetString(GL.GL_RENDERER),
functions.glGetString(GL.GL_VERSION),
functions.glGetString(GL.GL_SHADING_LANGUAGE_VERSION),
print_surface_format(self.context.format()),
print_surface_format(self.format()))
self.context.doneCurrent()
return text
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
hBoxLayout = QHBoxLayout(self)
self.plainTextEdit = QPlainTextEdit()
self.plainTextEdit.setMinimumWidth(400)
self.plainTextEdit.setReadOnly(True)
hBoxLayout.addWidget(self.plainTextEdit)
self.renderWindow = RenderWindow(QSurfaceFormat())
container = QWidget.createWindowContainer(self.renderWindow)
container.setMinimumSize(QSize(400, 400))
hBoxLayout.addWidget(container)
def updateDescription(self):
text = "{}\n\nPython {}\n\n{}".format(QLibraryInfo.build(), sys.version,
self.renderWindow.glInfo())
self.plainTextEdit.setPlainText(text)
if __name__ == '__main__':
parser = ArgumentParser(description="contextinfo", formatter_class=RawTextHelpFormatter)
parser.add_argument('--gles', '-g', action='store_true',
help='Use OpenGL ES')
parser.add_argument('--software', '-s', action='store_true',
help='Use Software OpenGL')
parser.add_argument('--desktop', '-d', action='store_true',
help='Use Desktop OpenGL')
options = parser.parse_args()
if options.gles:
QCoreApplication.setAttribute(Qt.AA_UseOpenGLES)
elif options.software:
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL)
elif options.desktop:
QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
mainWindow.updateDescription()
sys.exit(app.exec_())
examples/opengl/grabber.py 0000664 0000000 0000000 00000035515 13766170131 0016154 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/legacy/grabber example from Qt v5.x"""
import sys
import math
from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
try:
from OpenGL.GL import *
except ImportError:
app = QtWidgets.QApplication(sys.argv)
messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL grabber",
"PyOpenGL must be installed to run this example.",
QtWidgets.QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class GLWidget(QtOpenGL.QGLWidget):
xRotationChanged = QtCore.Signal(int)
yRotationChanged = QtCore.Signal(int)
zRotationChanged = QtCore.Signal(int)
def __init__(self, parent=None):
super(GLWidget, self).__init__(parent)
self.gear1 = 0
self.gear2 = 0
self.gear3 = 0
self.xRot = 0
self.yRot = 0
self.zRot = 0
self.gear1Rot = 0
timer = QtCore.QTimer(self)
timer.timeout.connect(self.advanceGears)
timer.start(20)
def freeResources(self):
self.makeCurrent()
glDeleteLists(self.gear1, 1)
glDeleteLists(self.gear2, 1)
glDeleteLists(self.gear3, 1)
def setXRotation(self, angle):
self.normalizeAngle(angle)
if angle != self.xRot:
self.xRot = angle
self.xRotationChanged.emit(angle)
self.updateGL()
def setYRotation(self, angle):
self.normalizeAngle(angle)
if angle != self.yRot:
self.yRot = angle
self.yRotationChanged.emit(angle)
self.updateGL()
def setZRotation(self, angle):
self.normalizeAngle(angle)
if angle != self.zRot:
self.zRot = angle
self.zRotationChanged.emit(angle)
self.updateGL()
def initializeGL(self):
lightPos = (5.0, 5.0, 10.0, 1.0)
reflectance1 = (0.8, 0.1, 0.0, 1.0)
reflectance2 = (0.0, 0.8, 0.2, 1.0)
reflectance3 = (0.2, 0.2, 1.0, 1.0)
glLightfv(GL_LIGHT0, GL_POSITION, lightPos)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
self.gear1 = self.makeGear(reflectance1, 1.0, 4.0, 1.0, 0.7, 20)
self.gear2 = self.makeGear(reflectance2, 0.5, 2.0, 2.0, 0.7, 10)
self.gear3 = self.makeGear(reflectance3, 1.3, 2.0, 0.5, 0.7, 10)
glEnable(GL_NORMALIZE)
glClearColor(0.0, 0.0, 0.0, 1.0)
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
self.drawGear(self.gear1, -3.0, -2.0, 0.0, self.gear1Rot / 16.0)
self.drawGear(self.gear2, +3.1, -2.0, 0.0,
-2.0 * (self.gear1Rot / 16.0) - 9.0)
glRotated(+90.0, 1.0, 0.0, 0.0)
self.drawGear(self.gear3, -3.1, -1.8, -2.2,
+2.0 * (self.gear1Rot / 16.0) - 2.0)
glPopMatrix()
def resizeGL(self, width, height):
side = min(width, height)
if side < 0:
return
glViewport(int((width - side) / 2), int((height - side) / 2), side, side)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glFrustum(-1.0, +1.0, -1.0, 1.0, 5.0, 60.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslated(0.0, 0.0, -40.0)
def mousePressEvent(self, event):
self.lastPos = event.pos()
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & QtCore.Qt.LeftButton:
self.setXRotation(self.xRot + 8 * dy)
self.setYRotation(self.yRot + 8 * dx)
elif event.buttons() & QtCore.Qt.RightButton:
self.setXRotation(self.xRot + 8 * dy)
self.setZRotation(self.zRot + 8 * dx)
self.lastPos = event.pos()
def advanceGears(self):
self.gear1Rot += 2 * 16
self.updateGL()
def xRotation(self):
return self.xRot
def yRotation(self):
return self.yRot
def zRotation(self):
return self.zRot
def makeGear(self, reflectance, innerRadius, outerRadius, thickness, toothSize, toothCount):
list = glGenLists(1)
glNewList(list, GL_COMPILE)
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, reflectance)
r0 = innerRadius
r1 = outerRadius - toothSize / 2.0
r2 = outerRadius + toothSize / 2.0
delta = (2.0 * math.pi / toothCount) / 4.0
z = thickness / 2.0
glShadeModel(GL_FLAT)
for i in range(2):
if i == 0:
sign = +1.0
else:
sign = -1.0
glNormal3d(0.0, 0.0, sign)
glBegin(GL_QUAD_STRIP)
for j in range(toothCount+1):
angle = 2.0 * math.pi * j / toothCount
glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), sign * z)
glVertex3d(r1 * math.cos(angle), r1 * math.sin(angle), sign * z)
glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), sign * z)
glVertex3d(r1 * math.cos(angle + 3 * delta), r1 * math.sin(angle + 3 * delta), sign * z)
glEnd()
glBegin(GL_QUADS)
for j in range(toothCount):
angle = 2.0 * math.pi * j / toothCount
glVertex3d(r1 * math.cos(angle), r1 * math.sin(angle), sign * z)
glVertex3d(r2 * math.cos(angle + delta), r2 * math.sin(angle + delta), sign * z)
glVertex3d(r2 * math.cos(angle + 2 * delta), r2 * math.sin(angle + 2 * delta), sign * z)
glVertex3d(r1 * math.cos(angle + 3 * delta), r1 * math.sin(angle + 3 * delta), sign * z)
glEnd()
glBegin(GL_QUAD_STRIP)
for i in range(toothCount):
for j in range(2):
angle = 2.0 * math.pi * (i + (j / 2.0)) / toothCount
s1 = r1
s2 = r2
if j == 1:
s1, s2 = s2, s1
glNormal3d(math.cos(angle), math.sin(angle), 0.0)
glVertex3d(s1 * math.cos(angle), s1 * math.sin(angle), +z)
glVertex3d(s1 * math.cos(angle), s1 * math.sin(angle), -z)
glNormal3d(s2 * math.sin(angle + delta) - s1 * math.sin(angle), s1 * math.cos(angle) - s2 * math.cos(angle + delta), 0.0)
glVertex3d(s2 * math.cos(angle + delta), s2 * math.sin(angle + delta), +z)
glVertex3d(s2 * math.cos(angle + delta), s2 * math.sin(angle + delta), -z)
glVertex3d(r1, 0.0, +z)
glVertex3d(r1, 0.0, -z)
glEnd()
glShadeModel(GL_SMOOTH)
glBegin(GL_QUAD_STRIP)
for i in range(toothCount+1):
angle = i * 2.0 * math.pi / toothCount
glNormal3d(-math.cos(angle), -math.sin(angle), 0.0)
glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), +z)
glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), -z)
glEnd()
glEndList()
return list
def drawGear(self, gear, dx, dy, dz, angle):
glPushMatrix()
glTranslated(dx, dy, dz)
glRotated(angle, 0.0, 0.0, 1.0)
glCallList(gear)
glPopMatrix()
def normalizeAngle(self, angle):
while (angle < 0):
angle += 360 * 16
while (angle > 360 * 16):
angle -= 360 * 16
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
centralWidget = QtWidgets.QWidget()
self.setCentralWidget(centralWidget)
self.glWidget = GLWidget()
self.pixmapLabel = QtWidgets.QLabel()
self.glWidgetArea = QtWidgets.QScrollArea()
self.glWidgetArea.setWidget(self.glWidget)
self.glWidgetArea.setWidgetResizable(True)
self.glWidgetArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.glWidgetArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.glWidgetArea.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
QtWidgets.QSizePolicy.Ignored)
self.glWidgetArea.setMinimumSize(50, 50)
self.pixmapLabelArea = QtWidgets.QScrollArea()
self.pixmapLabelArea.setWidget(self.pixmapLabel)
self.pixmapLabelArea.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
QtWidgets.QSizePolicy.Ignored)
self.pixmapLabelArea.setMinimumSize(50, 50)
xSlider = self.createSlider(self.glWidget.xRotationChanged,
self.glWidget.setXRotation)
ySlider = self.createSlider(self.glWidget.yRotationChanged,
self.glWidget.setYRotation)
zSlider = self.createSlider(self.glWidget.zRotationChanged,
self.glWidget.setZRotation)
self.createActions()
self.createMenus()
centralLayout = QtWidgets.QGridLayout()
centralLayout.addWidget(self.glWidgetArea, 0, 0)
centralLayout.addWidget(self.pixmapLabelArea, 0, 1)
centralLayout.addWidget(xSlider, 1, 0, 1, 2)
centralLayout.addWidget(ySlider, 2, 0, 1, 2)
centralLayout.addWidget(zSlider, 3, 0, 1, 2)
centralWidget.setLayout(centralLayout)
xSlider.setValue(15 * 16)
ySlider.setValue(345 * 16)
zSlider.setValue(0 * 16)
self.setWindowTitle("Grabber")
self.resize(400, 300)
def renderIntoPixmap(self):
size = self.getSize()
if size.isValid():
pixmap = self.glWidget.renderPixmap(size.width(), size.height())
self.setPixmap(pixmap)
def grabFrameBuffer(self):
image = self.glWidget.grabFrameBuffer()
self.setPixmap(QtGui.QPixmap.fromImage(image))
def clearPixmap(self):
self.setPixmap(QtGui.QPixmap())
def about(self):
QtWidgets.QMessageBox.about(self, "About Grabber",
"The Grabber example demonstrates two approaches for "
"rendering OpenGL into a Qt pixmap.")
def createActions(self):
self.renderIntoPixmapAct = QtWidgets.QAction("&Render into Pixmap...",
self, shortcut="Ctrl+R", triggered=self.renderIntoPixmap)
self.grabFrameBufferAct = QtWidgets.QAction("&Grab Frame Buffer", self,
shortcut="Ctrl+G", triggered=self.grabFrameBuffer)
self.clearPixmapAct = QtWidgets.QAction("&Clear Pixmap", self,
shortcut="Ctrl+L", triggered=self.clearPixmap)
self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q",
triggered=self.close)
self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)
self.aboutQtAct = QtWidgets.QAction("About &Qt", self,
triggered=qApp.aboutQt)
def createMenus(self):
self.fileMenu = self.menuBar().addMenu("&File")
self.fileMenu.addAction(self.renderIntoPixmapAct)
self.fileMenu.addAction(self.grabFrameBufferAct)
self.fileMenu.addAction(self.clearPixmapAct)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct)
self.helpMenu = self.menuBar().addMenu("&Help")
self.helpMenu.addAction(self.aboutAct)
self.helpMenu.addAction(self.aboutQtAct)
def createSlider(self, changedSignal, setterSlot):
slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
slider.setRange(0, 360 * 16)
slider.setSingleStep(16)
slider.setPageStep(15 * 16)
slider.setTickInterval(15 * 16)
slider.setTickPosition(QtWidgets.QSlider.TicksRight)
slider.valueChanged.connect(setterSlot)
changedSignal.connect(slider.setValue)
return slider
def setPixmap(self, pixmap):
self.pixmapLabel.setPixmap(pixmap)
size = pixmap.size()
if size - QtCore.QSize(1, 0) == self.pixmapLabelArea.maximumViewportSize():
size -= QtCore.QSize(1, 0)
self.pixmapLabel.resize(size)
def getSize(self):
text, ok = QtWidgets.QInputDialog.getText(self, "Grabber",
"Enter pixmap size:", QtWidgets.QLineEdit.Normal,
"%d x %d" % (self.glWidget.width(), self.glWidget.height()))
if not ok:
return QtCore.QSize()
regExp = QtCore.QRegularExpression("([0-9]+) *x *([0-9]+)")
assert regExp.isValid()
match = regExp.match(text)
if match.hasMatch():
width = int(match.captured(1))
height = int(match.captured(2))
if width > 0 and width < 2048 and height > 0 and height < 2048:
return QtCore.QSize(width, height)
return self.glWidget.size()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
res = app.exec_()
mainWin.glWidget.freeResources()
sys.exit(res)
examples/opengl/hellogl.py 0000664 0000000 0000000 00000022743 13766170131 0016175 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/legacy/hellogl example from Qt v5.x"""
import sys
import math
from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
try:
from OpenGL import GL
except ImportError:
app = QtWidgets.QApplication(sys.argv)
messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL hellogl",
"PyOpenGL must be installed to run this example.",
QtWidgets.QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class Window(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.glWidget = GLWidget()
self.xSlider = self.createSlider(QtCore.SIGNAL("xRotationChanged(int)"),
self.glWidget.setXRotation)
self.ySlider = self.createSlider(QtCore.SIGNAL("yRotationChanged(int)"),
self.glWidget.setYRotation)
self.zSlider = self.createSlider(QtCore.SIGNAL("zRotationChanged(int)"),
self.glWidget.setZRotation)
mainLayout = QtWidgets.QHBoxLayout()
mainLayout.addWidget(self.glWidget)
mainLayout.addWidget(self.xSlider)
mainLayout.addWidget(self.ySlider)
mainLayout.addWidget(self.zSlider)
self.setLayout(mainLayout)
self.xSlider.setValue(170 * 16)
self.ySlider.setValue(160 * 16)
self.zSlider.setValue(90 * 16)
self.setWindowTitle(self.tr("Hello GL"))
def createSlider(self, changedSignal, setterSlot):
slider = QtWidgets.QSlider(QtCore.Qt.Vertical)
slider.setRange(0, 360 * 16)
slider.setSingleStep(16)
slider.setPageStep(15 * 16)
slider.setTickInterval(15 * 16)
slider.setTickPosition(QtWidgets.QSlider.TicksRight)
self.glWidget.connect(slider, QtCore.SIGNAL("valueChanged(int)"), setterSlot)
self.connect(self.glWidget, changedSignal, slider, QtCore.SLOT("setValue(int)"))
return slider
class GLWidget(QtOpenGL.QGLWidget):
xRotationChanged = QtCore.Signal(int)
yRotationChanged = QtCore.Signal(int)
zRotationChanged = QtCore.Signal(int)
def __init__(self, parent=None):
QtOpenGL.QGLWidget.__init__(self, parent)
self.object = 0
self.xRot = 0
self.yRot = 0
self.zRot = 0
self.lastPos = QtCore.QPoint()
self.trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
self.trolltechPurple = QtGui.QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)
def xRotation(self):
return self.xRot
def yRotation(self):
return self.yRot
def zRotation(self):
return self.zRot
def minimumSizeHint(self):
return QtCore.QSize(50, 50)
def sizeHint(self):
return QtCore.QSize(400, 400)
def setXRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.xRot:
self.xRot = angle
self.emit(QtCore.SIGNAL("xRotationChanged(int)"), angle)
self.updateGL()
def setYRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.yRot:
self.yRot = angle
self.emit(QtCore.SIGNAL("yRotationChanged(int)"), angle)
self.updateGL()
def setZRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.zRot:
self.zRot = angle
self.emit(QtCore.SIGNAL("zRotationChanged(int)"), angle)
self.updateGL()
def initializeGL(self):
self.qglClearColor(self.trolltechPurple.darker())
self.object = self.makeObject()
GL.glShadeModel(GL.GL_FLAT)
GL.glEnable(GL.GL_DEPTH_TEST)
GL.glEnable(GL.GL_CULL_FACE)
def paintGL(self):
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glLoadIdentity()
GL.glTranslated(0.0, 0.0, -10.0)
GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
GL.glCallList(self.object)
def resizeGL(self, width, height):
side = min(width, height)
GL.glViewport(int((width - side) / 2),int((height - side) / 2), side, side)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GL.glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0)
GL.glMatrixMode(GL.GL_MODELVIEW)
def mousePressEvent(self, event):
self.lastPos = QtCore.QPoint(event.pos())
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & QtCore.Qt.LeftButton:
self.setXRotation(self.xRot + 8 * dy)
self.setYRotation(self.yRot + 8 * dx)
elif event.buttons() & QtCore.Qt.RightButton:
self.setXRotation(self.xRot + 8 * dy)
self.setZRotation(self.zRot + 8 * dx)
self.lastPos = QtCore.QPoint(event.pos())
def makeObject(self):
genList = GL.glGenLists(1)
GL.glNewList(genList, GL.GL_COMPILE)
GL.glBegin(GL.GL_QUADS)
x1 = +0.06
y1 = -0.14
x2 = +0.14
y2 = -0.06
x3 = +0.08
y3 = +0.00
x4 = +0.30
y4 = +0.22
self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
self.extrude(x1, y1, x2, y2)
self.extrude(x2, y2, y2, x2)
self.extrude(y2, x2, y1, x1)
self.extrude(y1, x1, x1, y1)
self.extrude(x3, y3, x4, y4)
self.extrude(x4, y4, y4, x4)
self.extrude(y4, x4, y3, x3)
Pi = 3.14159265358979323846
NumSectors = 200
for i in range(NumSectors):
angle1 = (i * 2 * Pi) / NumSectors
x5 = 0.30 * math.sin(angle1)
y5 = 0.30 * math.cos(angle1)
x6 = 0.20 * math.sin(angle1)
y6 = 0.20 * math.cos(angle1)
angle2 = ((i + 1) * 2 * Pi) / NumSectors
x7 = 0.20 * math.sin(angle2)
y7 = 0.20 * math.cos(angle2)
x8 = 0.30 * math.sin(angle2)
y8 = 0.30 * math.cos(angle2)
self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
self.extrude(x6, y6, x7, y7)
self.extrude(x8, y8, x5, y5)
GL.glEnd()
GL.glEndList()
return genList
def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
self.qglColor(self.trolltechGreen)
GL.glVertex3d(x1, y1, +0.05)
GL.glVertex3d(x2, y2, +0.05)
GL.glVertex3d(x3, y3, +0.05)
GL.glVertex3d(x4, y4, +0.05)
GL.glVertex3d(x4, y4, -0.05)
GL.glVertex3d(x3, y3, -0.05)
GL.glVertex3d(x2, y2, -0.05)
GL.glVertex3d(x1, y1, -0.05)
def extrude(self, x1, y1, x2, y2):
self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1)))
GL.glVertex3d(x1, y1, -0.05)
GL.glVertex3d(x2, y2, -0.05)
GL.glVertex3d(x2, y2, +0.05)
GL.glVertex3d(x1, y1, +0.05)
def normalizeAngle(self, angle):
while angle < 0:
angle += 360 * 16
while angle > 360 * 16:
angle -= 360 * 16
return angle
def freeResources(self):
self.makeCurrent()
GL.glDeleteLists(self.object, 1)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
res = app.exec_()
window.glWidget.freeResources()
sys.exit(res)
examples/opengl/hellogl2.py 0000664 0000000 0000000 00000040414 13766170131 0016252 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2018 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/hellogl2 example from Qt v5.x"""
import sys
import math
import numpy
import ctypes
from PySide2.QtCore import QCoreApplication, Signal, SIGNAL, SLOT, Qt, QSize, QPoint
from PySide2.QtGui import (QVector3D, QOpenGLFunctions, QOpenGLVertexArrayObject, QOpenGLBuffer,
QOpenGLShaderProgram, QMatrix4x4, QOpenGLShader, QOpenGLContext, QSurfaceFormat)
from PySide2.QtWidgets import (QApplication, QWidget, QMessageBox, QHBoxLayout, QSlider,
QOpenGLWidget)
from shiboken2 import VoidPtr
try:
from OpenGL import GL
except ImportError:
app = QApplication(sys.argv)
messageBox = QMessageBox(QMessageBox.Critical, "OpenGL hellogl",
"PyOpenGL must be installed to run this example.",
QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.glWidget = GLWidget()
self.xSlider = self.createSlider(SIGNAL("xRotationChanged(int)"),
self.glWidget.setXRotation)
self.ySlider = self.createSlider(SIGNAL("yRotationChanged(int)"),
self.glWidget.setYRotation)
self.zSlider = self.createSlider(SIGNAL("zRotationChanged(int)"),
self.glWidget.setZRotation)
mainLayout = QHBoxLayout()
mainLayout.addWidget(self.glWidget)
mainLayout.addWidget(self.xSlider)
mainLayout.addWidget(self.ySlider)
mainLayout.addWidget(self.zSlider)
self.setLayout(mainLayout)
self.xSlider.setValue(15 * 16)
self.ySlider.setValue(345 * 16)
self.zSlider.setValue(0 * 16)
self.setWindowTitle(self.tr("Hello GL"))
def createSlider(self, changedSignal, setterSlot):
slider = QSlider(Qt.Vertical)
slider.setRange(0, 360 * 16)
slider.setSingleStep(16)
slider.setPageStep(15 * 16)
slider.setTickInterval(15 * 16)
slider.setTickPosition(QSlider.TicksRight)
self.glWidget.connect(slider, SIGNAL("valueChanged(int)"), setterSlot)
self.connect(self.glWidget, changedSignal, slider, SLOT("setValue(int)"))
return slider
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.close()
else:
super(Window, self).keyPressEvent(event)
class Logo():
def __init__(self):
self.m_count = 0
self.i = 0
self.m_data = numpy.empty(2500 * 6, dtype = ctypes.c_float)
x1 = +0.06
y1 = -0.14
x2 = +0.14
y2 = -0.06
x3 = +0.08
y3 = +0.00
x4 = +0.30
y4 = +0.22
self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
self.extrude(x1, y1, x2, y2)
self.extrude(x2, y2, y2, x2)
self.extrude(y2, x2, y1, x1)
self.extrude(y1, x1, x1, y1)
self.extrude(x3, y3, x4, y4)
self.extrude(x4, y4, y4, x4)
self.extrude(y4, x4, y3, x3)
Pi = 3.14159265358979323846
NumSectors = 100
for i in range(NumSectors):
angle = (i * 2 * Pi) / NumSectors
x5 = 0.30 * math.sin(angle)
y5 = 0.30 * math.cos(angle)
x6 = 0.20 * math.sin(angle)
y6 = 0.20 * math.cos(angle)
angle = ((i + 1) * 2 * Pi) / NumSectors
x7 = 0.20 * math.sin(angle)
y7 = 0.20 * math.cos(angle)
x8 = 0.30 * math.sin(angle)
y8 = 0.30 * math.cos(angle)
self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
self.extrude(x6, y6, x7, y7)
self.extrude(x8, y8, x5, y5)
def constData(self):
return self.m_data.tobytes()
def count(self):
return self.m_count
def vertexCount(self):
return self.m_count / 6
def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
n = QVector3D.normal(QVector3D(x4 - x1, y4 - y1, 0), QVector3D(x2 - x1, y2 - y1, 0))
self.add(QVector3D(x1, y1, -0.05), n)
self.add(QVector3D(x4, y4, -0.05), n)
self.add(QVector3D(x2, y2, -0.05), n)
self.add(QVector3D(x3, y3, -0.05), n)
self.add(QVector3D(x2, y2, -0.05), n)
self.add(QVector3D(x4, y4, -0.05), n)
n = QVector3D.normal(QVector3D(x1 - x4, y1 - y4, 0), QVector3D(x2 - x4, y2 - y4, 0))
self.add(QVector3D(x4, y4, 0.05), n)
self.add(QVector3D(x1, y1, 0.05), n)
self.add(QVector3D(x2, y2, 0.05), n)
self.add(QVector3D(x2, y2, 0.05), n)
self.add(QVector3D(x3, y3, 0.05), n)
self.add(QVector3D(x4, y4, 0.05), n)
def extrude(self, x1, y1, x2, y2):
n = QVector3D.normal(QVector3D(0, 0, -0.1), QVector3D(x2 - x1, y2 - y1, 0))
self.add(QVector3D(x1, y1, 0.05), n)
self.add(QVector3D(x1, y1, -0.05), n)
self.add(QVector3D(x2, y2, 0.05), n)
self.add(QVector3D(x2, y2, -0.05), n)
self.add(QVector3D(x2, y2, 0.05), n)
self.add(QVector3D(x1, y1, -0.05), n)
def add(self, v, n):
self.m_data[self.i] = v.x()
self.i += 1
self.m_data[self.i] = v.y()
self.i += 1
self.m_data[self.i] = v.z()
self.i += 1
self.m_data[self.i] = n.x()
self.i += 1
self.m_data[self.i] = n.y()
self.i += 1
self.m_data[self.i] = n.z()
self.i += 1
self.m_count += 6
class GLWidget(QOpenGLWidget, QOpenGLFunctions):
xRotationChanged = Signal(int)
yRotationChanged = Signal(int)
zRotationChanged = Signal(int)
def __init__(self, parent=None):
QOpenGLWidget.__init__(self, parent)
QOpenGLFunctions.__init__(self)
self.core = "--coreprofile" in QCoreApplication.arguments()
self.xRot = 0
self.yRot = 0
self.zRot = 0
self.lastPos = 0
self.logo = Logo()
self.vao = QOpenGLVertexArrayObject()
self.logoVbo = QOpenGLBuffer()
self.program = QOpenGLShaderProgram()
self.projMatrixLoc = 0
self.mvMatrixLoc = 0
self.normalMatrixLoc = 0
self.lightPosLoc = 0
self.proj = QMatrix4x4()
self.camera = QMatrix4x4()
self.world = QMatrix4x4()
self.transparent = "--transparent" in QCoreApplication.arguments()
if self.transparent:
fmt = self.format()
fmt.setAlphaBufferSize(8)
self.setFormat(fmt)
def xRotation(self):
return self.xRot
def yRotation(self):
return self.yRot
def zRotation(self):
return self.zRot
def minimumSizeHint(self):
return QSize(50, 50)
def sizeHint(self):
return QSize(400, 400)
def normalizeAngle(self, angle):
while angle < 0:
angle += 360 * 16
while angle > 360 * 16:
angle -= 360 * 16
return angle
def setXRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.xRot:
self.xRot = angle
self.emit(SIGNAL("xRotationChanged(int)"), angle)
self.update()
def setYRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.yRot:
self.yRot = angle
self.emit(SIGNAL("yRotationChanged(int)"), angle)
self.update()
def setZRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.zRot:
self.zRot = angle
self.emit(SIGNAL("zRotationChanged(int)"), angle)
self.update()
def cleanup(self):
self.makeCurrent()
self.logoVbo.destroy()
del self.program
self.program = None
self.doneCurrent()
def vertexShaderSourceCore(self):
return """#version 150
in vec4 vertex;
in vec3 normal;
out vec3 vert;
out vec3 vertNormal;
uniform mat4 projMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
void main() {
vert = vertex.xyz;
vertNormal = normalMatrix * normal;
gl_Position = projMatrix * mvMatrix * vertex;
}"""
def fragmentShaderSourceCore(self):
return """#version 150
in highp vec3 vert;
in highp vec3 vertNormal;
out highp vec4 fragColor;
uniform highp vec3 lightPos;
void main() {
highp vec3 L = normalize(lightPos - vert);
highp float NL = max(dot(normalize(vertNormal), L), 0.0);
highp vec3 color = vec3(0.39, 1.0, 0.0);
highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);
fragColor = vec4(col, 1.0);
}"""
def vertexShaderSource(self):
return """attribute vec4 vertex;
attribute vec3 normal;
varying vec3 vert;
varying vec3 vertNormal;
uniform mat4 projMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
void main() {
vert = vertex.xyz;
vertNormal = normalMatrix * normal;
gl_Position = projMatrix * mvMatrix * vertex;
}"""
def fragmentShaderSource(self):
return """varying highp vec3 vert;
varying highp vec3 vertNormal;
uniform highp vec3 lightPos;
void main() {
highp vec3 L = normalize(lightPos - vert);
highp float NL = max(dot(normalize(vertNormal), L), 0.0);
highp vec3 color = vec3(0.39, 1.0, 0.0);
highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);
gl_FragColor = vec4(col, 1.0);
}"""
def initializeGL(self):
self.context().aboutToBeDestroyed.connect(self.cleanup)
self.initializeOpenGLFunctions()
self.glClearColor(0, 0, 0, 1)
self.program = QOpenGLShaderProgram()
if self.core:
self.vertexShader = self.vertexShaderSourceCore()
self.fragmentShader = self.fragmentShaderSourceCore()
else:
self.vertexShader = self.vertexShaderSource()
self.fragmentShader = self.fragmentShaderSource()
self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self.vertexShader)
self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self.fragmentShader)
self.program.bindAttributeLocation("vertex", 0)
self.program.bindAttributeLocation("normal", 1)
self.program.link()
self.program.bind()
self.projMatrixLoc = self.program.uniformLocation("projMatrix")
self.mvMatrixLoc = self.program.uniformLocation("mvMatrix")
self.normalMatrixLoc = self.program.uniformLocation("normalMatrix")
self.lightPosLoc = self.program.uniformLocation("lightPos")
self.vao.create()
vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
self.logoVbo.create()
self.logoVbo.bind()
float_size = ctypes.sizeof(ctypes.c_float)
self.logoVbo.allocate(self.logo.constData(), self.logo.count() * float_size)
self.setupVertexAttribs()
self.camera.setToIdentity()
self.camera.translate(0, 0, -1)
self.program.setUniformValue(self.lightPosLoc, QVector3D(0, 0, 70))
self.program.release()
vaoBinder = None
def setupVertexAttribs(self):
self.logoVbo.bind()
f = QOpenGLContext.currentContext().functions()
f.glEnableVertexAttribArray(0)
f.glEnableVertexAttribArray(1)
float_size = ctypes.sizeof(ctypes.c_float)
null = VoidPtr(0)
pointer = VoidPtr(3 * float_size)
f.glVertexAttribPointer(0, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, null)
f.glVertexAttribPointer(1, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, pointer)
self.logoVbo.release()
def paintGL(self):
self.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
self.glEnable(GL.GL_DEPTH_TEST)
self.glEnable(GL.GL_CULL_FACE)
self.world.setToIdentity()
self.world.rotate(180 - (self.xRot / 16), 1, 0, 0)
self.world.rotate(self.yRot / 16, 0, 1, 0)
self.world.rotate(self.zRot / 16, 0, 0, 1)
vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
self.program.bind()
self.program.setUniformValue(self.projMatrixLoc, self.proj)
self.program.setUniformValue(self.mvMatrixLoc, self.camera * self.world)
normalMatrix = self.world.normalMatrix()
self.program.setUniformValue(self.normalMatrixLoc, normalMatrix)
self.glDrawArrays(GL.GL_TRIANGLES, 0, self.logo.vertexCount())
self.program.release()
vaoBinder = None
def resizeGL(self, width, height):
self.proj.setToIdentity()
self.proj.perspective(45, width / height, 0.01, 100)
def mousePressEvent(self, event):
self.lastPos = QPoint(event.pos())
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & Qt.LeftButton:
self.setXRotation(self.xRot + 8 * dy)
self.setYRotation(self.yRot + 8 * dx)
elif event.buttons() & Qt.RightButton:
self.setXRotation(self.xRot + 8 * dy)
self.setZRotation(self.zRot + 8 * dx)
self.lastPos = QPoint(event.pos())
if __name__ == '__main__':
app = QApplication(sys.argv)
fmt = QSurfaceFormat()
fmt.setDepthBufferSize(24)
if "--multisample" in QCoreApplication.arguments():
fmt.setSamples(4)
if "--coreprofile" in QCoreApplication.arguments():
fmt.setVersion(3, 2)
fmt.setProfile(QSurfaceFormat.CoreProfile)
QSurfaceFormat.setDefaultFormat(fmt)
mainWindow = Window()
if "--transparent" in QCoreApplication.arguments():
mainWindow.setAttribute(Qt.WA_TranslucentBackground)
mainWindow.setAttribute(Qt.WA_NoSystemBackground, False)
mainWindow.resize(mainWindow.sizeHint())
mainWindow.show()
res = app.exec_()
sys.exit(res)
examples/opengl/opengl.pyproject 0000664 0000000 0000000 00000000243 13766170131 0017411 0 ustar 00root root 0000000 0000000 {
"files": ["grabber.py", "samplebuffers.py", "hellogl.py",
"hellogl2.py", "contextinfo.py", "2dpainting.py",
"overpainting.py"]
}
examples/opengl/overpainting.py 0000664 0000000 0000000 00000032174 13766170131 0017253 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/legacy/overpainting example from Qt v5.x"""
import sys
import math, random
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtOpenGL import *
try:
from OpenGL.GL import *
except ImportError:
app = QApplication(sys.argv)
messageBox = QMessageBox(QMessageBox.Critical, "OpenGL overpainting",
"PyOpenGL must be installed to run this example.",
QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class Bubble:
def __init__(self, position, radius, velocity):
self.position = position
self.vel = velocity
self.radius = radius
self.innerColor = self.randomColor()
self.outerColor = self.randomColor()
self.updateBrush()
def updateBrush(self):
gradient = QRadialGradient(QPointF(self.radius, self.radius), self.radius,
QPointF(self.radius*0.5, self.radius*0.5))
gradient.setColorAt(0, QColor(255, 255, 255, 255))
gradient.setColorAt(0.25, self.innerColor)
gradient.setColorAt(1, self.outerColor)
self.brush = QBrush(gradient)
def drawBubble(self, painter):
painter.save()
painter.translate(self.position.x() - self.radius,
self.position.y() - self.radius)
painter.setBrush(self.brush)
painter.drawEllipse(0, 0, int(2*self.radius), int(2*self.radius))
painter.restore()
def randomColor(self):
red = random.randrange(205, 256)
green = random.randrange(205, 256)
blue = random.randrange(205, 256)
alpha = random.randrange(91, 192)
return QColor(red, green, blue, alpha)
def move(self, bbox):
self.position += self.vel
leftOverflow = self.position.x() - self.radius - bbox.left()
rightOverflow = self.position.x() + self.radius - bbox.right()
topOverflow = self.position.y() - self.radius - bbox.top()
bottomOverflow = self.position.y() + self.radius - bbox.bottom()
if leftOverflow < 0.0:
self.position.setX(self.position.x() - 2 * leftOverflow)
self.vel.setX(-self.vel.x())
elif rightOverflow > 0.0:
self.position.setX(self.position.x() - 2 * rightOverflow)
self.vel.setX(-self.vel.x())
if topOverflow < 0.0:
self.position.setY(self.position.y() - 2 * topOverflow)
self.vel.setY(-self.vel.y())
elif bottomOverflow > 0.0:
self.position.setY(self.position.y() - 2 * bottomOverflow)
self.vel.setY(-self.vel.y())
def rect(self):
return QRectF(self.position.x() - self.radius,
self.position.y() - self.radius,
2 * self.radius, 2 * self.radius)
class GLWidget(QGLWidget):
def __init__(self, parent = None):
QGLWidget.__init__(self, QGLFormat(QGL.SampleBuffers), parent)
midnight = QTime(0, 0, 0)
random.seed(midnight.secsTo(QTime.currentTime()))
self.object = 0
self.xRot = 0
self.yRot = 0
self.zRot = 0
self.image = QImage()
self.bubbles = []
self.lastPos = QPoint()
self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)
self.animationTimer = QTimer()
self.animationTimer.setSingleShot(False)
self.connect(self.animationTimer, SIGNAL("timeout()"), self.animate)
self.animationTimer.start(25)
self.setAttribute(Qt.WA_NoSystemBackground)
self.setMinimumSize(200, 200)
self.setWindowTitle(self.tr("Overpainting a Scene"))
def freeResources(self):
self.makeCurrent()
glDeleteLists(self.object, 1)
def setXRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.xRot:
self.xRot = angle
self.emit(SIGNAL("xRotationChanged(int)"), angle)
def setYRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.yRot:
self.yRot = angle
self.emit(SIGNAL("yRotationChanged(int)"), angle)
def setZRotation(self, angle):
angle = self.normalizeAngle(angle)
if angle != self.zRot:
self.zRot = angle
self.emit(SIGNAL("zRotationChanged(int)"), angle)
def initializeGL(self):
self.object = self.makeObject()
def mousePressEvent(self, event):
self.lastPos = QPoint(event.pos())
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & Qt.LeftButton:
self.setXRotation(self.xRot + 8 * dy)
self.setYRotation(self.yRot + 8 * dx)
elif event.buttons() & Qt.RightButton:
self.setXRotation(self.xRot + 8 * dy)
self.setZRotation(self.zRot + 8 * dx)
self.lastPos = QPoint(event.pos())
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
glPushAttrib(GL_ALL_ATTRIB_BITS)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
self.qglClearColor(self.trolltechPurple.darker())
glShadeModel(GL_SMOOTH)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
lightPosition = ( 0.5, 5.0, 7.0, 1.0 )
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition)
self.resizeGL(self.width(), self.height())
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslated(0.0, 0.0, -10.0)
glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
glCallList(self.object)
glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glDisable(GL_CULL_FACE) ### not required if begin() also does it
for bubble in self.bubbles:
if bubble.rect().intersects(QRectF(event.rect())):
bubble.drawBubble(painter)
painter.drawImage((self.width() - self.image.width())/2, 0, self.image)
painter.end()
def resizeGL(self, width, height):
side = min(width, height)
glViewport(int((width - side) / 2), int((height - side) / 2), side, side)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
glMatrixMode(GL_MODELVIEW)
self.formatInstructions(width, height)
def showEvent(self, event):
self.createBubbles(20 - len(self.bubbles))
def sizeHint(self):
return QSize(400, 400)
def makeObject(self):
list = glGenLists(1)
glNewList(list, GL_COMPILE)
glEnable(GL_NORMALIZE)
glBegin(GL_QUADS)
logoDiffuseColor = (self.trolltechGreen.red()/255.0,
self.trolltechGreen.green()/255.0,
self.trolltechGreen.blue()/255.0, 1.0)
glMaterialfv(GL_FRONT, GL_DIFFUSE, logoDiffuseColor)
x1 = +0.06
y1 = -0.14
x2 = +0.14
y2 = -0.06
x3 = +0.08
y3 = +0.00
x4 = +0.30
y4 = +0.22
self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
self.extrude(x1, y1, x2, y2)
self.extrude(x2, y2, y2, x2)
self.extrude(y2, x2, y1, x1)
self.extrude(y1, x1, x1, y1)
self.extrude(x3, y3, x4, y4)
self.extrude(x4, y4, y4, x4)
self.extrude(y4, x4, y3, x3)
NumSectors = 200
for i in range(NumSectors):
angle1 = (i * 2 * math.pi) / NumSectors
x5 = 0.30 * math.sin(angle1)
y5 = 0.30 * math.cos(angle1)
x6 = 0.20 * math.sin(angle1)
y6 = 0.20 * math.cos(angle1)
angle2 = ((i + 1) * 2 * math.pi) / NumSectors
x7 = 0.20 * math.sin(angle2)
y7 = 0.20 * math.cos(angle2)
x8 = 0.30 * math.sin(angle2)
y8 = 0.30 * math.cos(angle2)
self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
self.extrude(x6, y6, x7, y7)
self.extrude(x8, y8, x5, y5)
glEnd()
glEndList()
return list
def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
glNormal3d(0.0, 0.0, -1.0)
glVertex3d(x1, y1, -0.05)
glVertex3d(x2, y2, -0.05)
glVertex3d(x3, y3, -0.05)
glVertex3d(x4, y4, -0.05)
glNormal3d(0.0, 0.0, 1.0)
glVertex3d(x4, y4, +0.05)
glVertex3d(x3, y3, +0.05)
glVertex3d(x2, y2, +0.05)
glVertex3d(x1, y1, +0.05)
def extrude(self, x1, y1, x2, y2):
self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1)))
glNormal3d((x1 + x2)/2.0, (y1 + y2)/2.0, 0.0)
glVertex3d(x1, y1, +0.05)
glVertex3d(x2, y2, +0.05)
glVertex3d(x2, y2, -0.05)
glVertex3d(x1, y1, -0.05)
def normalizeAngle(self, angle):
while angle < 0:
angle += 360 * 16
while angle > 360 * 16:
angle -= 360 * 16
return angle
def createBubbles(self, number):
for i in range(number):
position = QPointF(self.width()*(0.1 + 0.8*random.random()),
self.height()*(0.1 + 0.8*random.random()))
radius = min(self.width(), self.height())*(0.0125 + 0.0875*random.random())
velocity = QPointF(self.width()*0.0125*(-0.5 + random.random()),
self.height()*0.0125*(-0.5 + random.random()))
self.bubbles.append(Bubble(position, radius, velocity))
def animate(self):
for bubble in self.bubbles:
self.update(bubble.rect().toRect())
bubble.move(self.rect())
self.update(bubble.rect().toRect())
def formatInstructions(self, width, height):
text = self.tr("Click and drag with the left mouse button "
"to rotate the Qt logo.")
metrics = QFontMetrics(self.font())
border = max(4, metrics.leading())
rect = metrics.boundingRect(0, 0, width - 2*border, int(height*0.125),
Qt.AlignCenter | Qt.TextWordWrap, text)
self.image = QImage(width, rect.height() + 2*border,
QImage.Format_ARGB32_Premultiplied)
self.image.fill(qRgba(0, 0, 0, 127))
painter = QPainter()
painter.begin(self.image)
painter.setRenderHint(QPainter.TextAntialiasing)
painter.setPen(Qt.white)
painter.drawText((width - rect.width())/2, border,
rect.width(), rect.height(),
Qt.AlignCenter | Qt.TextWordWrap, text)
painter.end()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = GLWidget()
window.show()
res = app.exec_()
window.freeResources()
sys.exit(res)
examples/opengl/samplebuffers.py 0000664 0000000 0000000 00000014650 13766170131 0017403 0 ustar 00root root 0000000 0000000
############################################################################
##
## Copyright (C) 2013 Riverbank Computing Limited.
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the Qt for Python examples of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:BSD$
## You may use this file under the terms of the BSD license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of The Qt Company Ltd nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
############################################################################
"""PySide2 port of the opengl/legacy/samplebuffers example from Qt v5.x"""
import sys
import math
from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
try:
from OpenGL import GL
except ImportError:
app = QtWidgets.QApplication(sys.argv)
messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL samplebuffers",
"PyOpenGL must be installed to run this example.",
QtWidgets.QMessageBox.Close)
messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
messageBox.exec_()
sys.exit(1)
class GLWidget(QtOpenGL.QGLWidget):
GL_MULTISAMPLE = 0x809D
rot = 0.0
def __init__(self, parent=None):
QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent)
self.list_ = []
self.startTimer(40)
self.setWindowTitle(self.tr("Sample Buffers"))
def initializeGL(self):
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GL.glOrtho( -.5, .5, .5, -.5, -1000, 1000)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glClearColor(1.0, 1.0, 1.0, 1.0)
self.makeObject()
def resizeGL(self, w, h):
GL.glViewport(0, 0, w, h)
def paintGL(self):
GL.glClear(GL.GL_COLOR_BUFFER_BIT)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glPushMatrix()
GL.glEnable(GLWidget.GL_MULTISAMPLE)
GL.glTranslatef( -0.25, -0.10, 0.0)
GL.glScalef(0.75, 1.15, 0.0)
GL.glRotatef(GLWidget.rot, 0.0, 0.0, 1.0)
GL.glCallList(self.list_)
GL.glPopMatrix()
GL.glPushMatrix()
GL.glDisable(GLWidget.GL_MULTISAMPLE)
GL.glTranslatef(0.25, -0.10, 0.0)
GL.glScalef(0.75, 1.15, 0.0)
GL.glRotatef(GLWidget.rot, 0.0, 0.0, 1.0)
GL.glCallList(self.list_)
GL.glPopMatrix()
GLWidget.rot += 0.2
self.qglColor(QtCore.Qt.black)
self.renderText(-0.35, 0.4, 0.0, "Multisampling enabled")
self.renderText(0.15, 0.4, 0.0, "Multisampling disabled")
def timerEvent(self, event):
self.update()
def makeObject(self):
trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
Pi = 3.14159265358979323846
NumSectors = 15
x1 = +0.06
y1 = -0.14
x2 = +0.14
y2 = -0.06
x3 = +0.08
y3 = +0.00
x4 = +0.30
y4 = +0.22
self.list_ = GL.glGenLists(1)
GL.glNewList(self.list_, GL.GL_COMPILE)
for i in range(NumSectors):
angle1 = float((i * 2 * Pi) / NumSectors)
x5 = 0.30 * math.sin(angle1)
y5 = 0.30 * math.cos(angle1)
x6 = 0.20 * math.sin(angle1)
y6 = 0.20 * math.cos(angle1)
angle2 = float(((i + 1) * 2 * Pi) / NumSectors)
x7 = 0.20 * math.sin(angle2)
y7 = 0.20 * math.cos(angle2)
x8 = 0.30 * math.sin(angle2)
y8 = 0.30 * math.cos(angle2)
self.qglColor(trolltechGreen)
self.quad(GL.GL_QUADS, x5, y5, x6, y6, x7, y7, x8, y8)
self.qglColor(QtCore.Qt.black)
self.quad(GL.GL_LINE_LOOP, x5, y5, x6, y6, x7, y7, x8, y8)
self.qglColor(trolltechGreen)
self.quad(GL.GL_QUADS, x1, y1, x2, y2, y2, x2, y1, x1)
self.quad(GL.GL_QUADS, x3, y3, x4, y4, y4, x4, y3, x3)
self.qglColor(QtCore.Qt.black)
self.quad(GL.GL_LINE_LOOP, x1, y1, x2, y2, y2, x2, y1, x1)
self.quad(GL.GL_LINE_LOOP, x3, y3, x4, y4, y4, x4, y3, x3)
GL.glEndList()
def quad(self, primitive, x1, y1, x2, y2, x3, y3, x4, y4):
GL.glBegin(primitive)
GL.glVertex2d(x1, y1)
GL.glVertex2d(x2, y2)
GL.glVertex2d(x3, y3)
GL.glVertex2d(x4, y4)
GL.glEnd()
def freeResources(self):
self.makeCurrent()
GL.glDeleteLists(self.list_, 1)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
if not QtOpenGL.QGLFormat.hasOpenGL():
QMessageBox.information(0, "OpenGL pbuffers",
"This system does not support OpenGL.",
QMessageBox.Ok)
sys.exit(1)
f = QtOpenGL.QGLFormat.defaultFormat()
f.setSampleBuffers(True)
QtOpenGL.QGLFormat.setDefaultFormat(f)
widget = GLWidget()
widget.resize(640, 480)
widget.show()
res = app.exec_()
widget.freeResources()
sys.exit(res)
examples/opengl/textures/ 0000775 0000000 0000000 00000000000 13766170131 0016050 5 ustar 00root root 0000000 0000000 examples/opengl/textures/images/ 0000775 0000000 0000000 00000000000 13766170131 0017315 5 ustar 00root root 0000000 0000000 examples/opengl/textures/images/side1.png 0000664 0000000 0000000 00000002024 13766170131 0021026 0 ustar 00root root 0000000 0000000 PNG
IHDR kXT PLTE| (0088@HPPXX`hhppxxĈȐȘ̘РԨذظܸ5up pHYs H H Fk> IDATxas@##il
bbmђr)8r~ΰ3]̝0 Z E y^w5h
; KҼ H[z n#o_* P̫**`£H[51(Cϲ[ vudqU,o; `~$e , l=fmՑ\w8 嗋4|.,'diӄ *Q̮2/J ; _$*\<^TS/-_: Pݴ6xl2r&* )?^|Z\HkYڂɏTϻ{7wJgSt˚RXYGߚSK<&IV6%