diff --git a/BUILD.md b/BUILD.md index 44c1c837c..ec1ff1200 100644 --- a/BUILD.md +++ b/BUILD.md @@ -25,7 +25,6 @@ Required: - [Autodesk Maya 2016+](https://www.autodesk.com.au/products/maya/overview) - [CMinpack 1.3.6](https://github.com/devernay/cminpack/releases/tag/v1.3.6) - [Python 2.7.x or 3.x](https://www.python.org/) (for build scripts) -- [Qt.py 1.1.0](https://github.com/mottosso/Qt.py/releases/tag/1.1.0) (for GUI support) - [Sphinx 1.8.3+](http://www.sphinx-doc.org/en/master/index.html) (for building documentation) Optional Solver: @@ -37,6 +36,10 @@ Optional Solver: - Note: The automatic build script for _levmar_ requires [CMake 3.4.3+](https://cmake.org/) with levmar on Windows. +Note: Until mmSolver v0.3.13 [Qt.py 1.1.0](https://github.com/mottosso/Qt.py/releases/tag/1.1.0) +was required for GUI support, but this is now embedded inside mmSolver +directly, so there is no need install it manually. + # Building Overview An overview of compiling is: @@ -56,9 +59,6 @@ $ cd # Download and Build CMinpack automatically. $ bash scripts/build_cminpack.bash -# Download Qt.py automatically. -$ bash scripts/build_qtpy.bash - # Build mmSolver, compile UI files, compile Maya plug-in, build # documentation, create module and install to home directory. $ bash scripts/build_mmSolver_linux_mayaXXXX.bash @@ -80,9 +80,6 @@ On Windows: # Download and Build CMinpack automatically. > scripts/build_cminpack.bat -# Download Qt.py automatically. -> scripts/build_qtpy.bat - :: Build mmSolver, compile UI files, compile Maya plug-in, build :: documentation, create module and install to home directory. > scripts/build_mmSolver_windows64_mayaXXXX.bat diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 53adffd92..b4f0048e2 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -54,7 +54,7 @@ Python 2.7.5 # Building Dependencies -`cminpack`, `levmar` and `Qt.py` can be easily downloaded and built +`cminpack`, and `levmar` can be easily downloaded and built for mmSolver using build scripts provided in the `/scripts` directory. @@ -62,7 +62,6 @@ On Linux: ```commandline $ cd $ bash scripts/build_cminpack.bash -$ bash scripts/build_qtpy.bash $ bash scripts/build_levmar.bash ``` @@ -71,15 +70,10 @@ directories under `/external/install`. - cminpack - levmar -- qtpy These dependencies will automatically be found by the mmSolver build script and installed. -If you do not want to install `Qt.py` into mmSolver, simply do not use -the build script and delete the directory `/external/install/qtpy`. - # Build mmSolver After installing CMinpack, you can now build mmSolver. @@ -310,27 +304,27 @@ Run in the Linux Bash terminal: # Maya 2016 $ load_maya2016.sh # Example script to set up Maya environment $ mkdir -p /media/dev/mayaMatchMoveSolver_maya2016Deploy_linux ; cd /media/dev/ ; git clone git@github.com:david-cattermole/mayaMatchMoveSolver.git mayaMatchMoveSolver_maya2016Deploy_linux -$ cd /media/dev/mayaMatchMoveSolver_maya2016Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_qtpy.bash ; bash scripts/build_mmSolver_linux_maya2016.bash +$ cd /media/dev/mayaMatchMoveSolver_maya2016Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_mmSolver_linux_maya2016.bash # Maya 2017 $ load_maya2017.sh # Example script to set up Maya environment $ mkdir -p /media/dev/mayaMatchMoveSolver_maya2017Deploy_linux ; cd /media/dev/ ; git clone git@github.com:david-cattermole/mayaMatchMoveSolver.git mayaMatchMoveSolver_maya2017Deploy_linux -$ cd /media/dev/mayaMatchMoveSolver_maya2017Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_qtpy.bash ; bash scripts/build_mmSolver_linux_maya2017.bash +$ cd /media/dev/mayaMatchMoveSolver_maya2017Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_mmSolver_linux_maya2017.bash # Maya 2018 $ load_maya2018.sh # Example script to set up Maya environment $ mkdir -p /media/dev/mayaMatchMoveSolver_maya2018Deploy_linux ; cd /media/dev/ ; git clone git@github.com:david-cattermole/mayaMatchMoveSolver.git mayaMatchMoveSolver_maya2018Deploy_linux -$ cd /media/dev/mayaMatchMoveSolver_maya2018Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_qtpy.bash ; bash scripts/build_mmSolver_linux_maya2018.bash +$ cd /media/dev/mayaMatchMoveSolver_maya2018Deploy_linux ; git fetch --all; git checkout -f master; git pull ; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_mmSolver_linux_maya2018.bash # Maya 2019 $ load_maya2019.sh # Example script to set up Maya environment $ mkdir -p /media/dev/mayaMatchMoveSolver_maya2019Deploy_linux ; cd /media/dev/ ; git clone git@github.com:david-cattermole/mayaMatchMoveSolver.git mayaMatchMoveSolver_maya2019Deploy_linux -$ cd /media/dev/mayaMatchMoveSolver_maya2019Deploy_linux ; git fetch --all; git checkout -f master; git pull; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_qtpy.bash ; bash scripts/build_mmSolver_linux_maya2019.bash +$ cd /media/dev/mayaMatchMoveSolver_maya2019Deploy_linux ; git fetch --all; git checkout -f master; git pull; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_mmSolver_linux_maya2019.bash # Maya 2020 $ load_maya2020.sh # Example script to set up Maya environment $ mkdir -p /media/dev/mayaMatchMoveSolver_maya2020Deploy_linux ; cd /media/dev/ ; git clone git@github.com:david-cattermole/mayaMatchMoveSolver.git mayaMatchMoveSolver_maya2020Deploy_linux -$ cd /media/dev/mayaMatchMoveSolver_maya2020Deploy_linux ; git fetch --all; git checkout -f master; git pull; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_qtpy.bash ; bash scripts/build_mmSolver_linux_maya2020.bash +$ cd /media/dev/mayaMatchMoveSolver_maya2020Deploy_linux ; git fetch --all; git checkout -f master; git pull; rm -R --force build_* ; rm -R --force external/install/* ; rm -R --force external/working/*/ ; bash scripts/build_cminpack.bash ; bash scripts/build_mmSolver_linux_maya2020.bash ``` Package files can then be uploaded from the diff --git a/BUILD_WINDOWS.md b/BUILD_WINDOWS.md index 97ecbb59e..6b4259007 100644 --- a/BUILD_WINDOWS.md +++ b/BUILD_WINDOWS.md @@ -35,7 +35,7 @@ It is *important* you use the `x64` Command Prompt, *not* mmSolver has a few dependencies, and are listed in [BUILD.md](https://github.com/david-cattermole/mayaMatchMoveSolver/blob/master/BUILD.md#dependencies). -`cminpack`, `levmar` and `Qt.py` can be easily downloaded and built +`cminpack`, and `levmar` can be easily downloaded and built for mmSolver using build scripts provided in the `\scripts` directory. @@ -43,7 +43,6 @@ On Windows: ```cmd > CD > scripts\build_cminpack.bat -> scripts\build_qtpy.bat > scripts\build_levmar.bat ``` @@ -52,15 +51,10 @@ directories under `\external\install`. - cminpack - levmar -- qtpy These dependencies will automatically be found by the mmSolver build script and installed. -If you do not want to install `Qt.py` into mmSolver, simply do not use -the build script and delete the directory `\external\install\qtpy`. - # Build mmSolver After installing CMinpack, you can now build mmSolver. @@ -317,19 +311,19 @@ Run in the Windows Command Prompt with the needed MSVC compiler environment path (For example run "VS2012 x64 Cross Tools Command Prompt" or "VS2015 x86 x64 Cross Tools Command Prompt") ```cmd REM Maya 2016 -> cd %userprofile%\dev\mayaMatchMoveSolver_maya2016Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_qtpy.bat && scripts\build_mmSolver_windows64_maya2016.bat +> cd %userprofile%\dev\mayaMatchMoveSolver_maya2016Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_mmSolver_windows64_maya2016.bat REM Maya 2017 -> cd %userprofile%\dev\mayaMatchMoveSolver_maya2017Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_qtpy.bat && scripts\build_mmSolver_windows64_maya2017.bat +> cd %userprofile%\dev\mayaMatchMoveSolver_maya2017Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_mmSolver_windows64_maya2017.bat REM Maya 2018 -> cd %userprofile%\dev\mayaMatchMoveSolver_maya2018Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_qtpy.bat && scripts\build_mmSolver_windows64_maya2018.bat +> cd %userprofile%\dev\mayaMatchMoveSolver_maya2018Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_mmSolver_windows64_maya2018.bat REM Maya 2019 -> cd %userprofile%\dev\mayaMatchMoveSolver_maya2019Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_qtpy.bat && scripts\build_mmSolver_windows64_maya2019.bat +> cd %userprofile%\dev\mayaMatchMoveSolver_maya2019Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_mmSolver_windows64_maya2019.bat REM Maya 2020 -> cd %userprofile%\dev\mayaMatchMoveSolver_maya2020Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_qtpy.bat && scripts\build_mmSolver_windows64_maya2020.bat +> cd %userprofile%\dev\mayaMatchMoveSolver_maya2020Deploy_windows64 && scripts\build_cminpack.bat && scripts\build_mmSolver_windows64_maya2020.bat ``` Package files can then be uploaded from the diff --git a/INSTALL.md b/INSTALL.md index a5fd882c5..b8a4150aa 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -18,30 +18,11 @@ For a simple installation, **do not** install from the `Source code (zip)` or `Source code (tar.gz)` archives. These archives are for developers only. -# Install Qt.py (in a Home Environment) +# Install Qt.py -*Maya MatchMove Solver* uses the very popular -[Qt.py](https://github.com/mottosso/Qt.py) project for it's -[Qt Framework](https://www.qt.io/) user interfaces. -Starting with mmSolver v0.2.0, `Qt.py` is installed with mmSolver, and -users do not need to install `Qt.py`. - -# Install Qt.py (in a Professional Environment) - -Starting with mmSolver v0.2.0, `Qt.py` is installed with mmSolver -pre-build packages on GitHub. -If `Qt.py` is already installed in your professional environment -(studio pipeline), you will not need to install it again. - -To remove `Qt.py` from the installation delete the folder named -`python_qt` in the module directory. - -***Warning:*** If you are installing *Maya MatchMove Solver* in a studio -production environment, *Qt.py* may already be installed. Installing a -custom version of *Qt.py* in to your home directory may override your -pipeline provided file and may cause unexpected problems. It is -recommended to check with your studio's Pipeline team **before** -installing any custom software. +In *Maya MatchMove Solver* v0.3.14 and above the +[Qt.py](https://github.com/mottosso/Qt.py) project is now included +inside mmSolver, there is no need to install it at all. # Install Maya Module @@ -83,10 +64,6 @@ automatically at start-up. You will see a message in the Script Editor `# root : MM Solver Startup... #`, and a new shelf will automatically be created for you named *mmSolver*. -***Note:*** Please remove the `/python_qt` directory, if -`Qt.py` is already installed, see the above note -*Install Qt.py (in a Professional Environment)*. - # Project Configuration By default, the tool should work without trouble, but some individuals diff --git a/docs/source/conf.py.in b/docs/source/conf.py.in index f9f93a1c7..2d6c71e3f 100644 --- a/docs/source/conf.py.in +++ b/docs/source/conf.py.in @@ -25,11 +25,11 @@ except ImportError: # Mocking... autodoc_mock_imports = [ - 'Qt', - 'Qt.QtCore', - 'Qt.QtGui', - 'Qt.QtWidgets', - 'Qt.QtCompat', + 'mmSolver.ui.Qt', + 'mmSolver.ui.Qt.QtCore', + 'mmSolver.ui.Qt.QtGui', + 'mmSolver.ui.Qt.QtWidgets', + 'mmSolver.ui.Qt.QtCompat', 'PySide', 'PySide2', 'shiboken', diff --git a/docs/source/licenses.rst b/docs/source/licenses.rst index fa0e976f1..c4104afe7 100644 --- a/docs/source/licenses.rst +++ b/docs/source/licenses.rst @@ -453,7 +453,7 @@ is distributed with mmSolver. :: The MIT License (MIT) - Copyright (c) 2016 Marcus Ottosson + Copyright (c) 2016-2017 Marcus Ottosson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -462,8 +462,8 @@ is distributed with mmSolver. :: copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -473,6 +473,76 @@ is distributed with mmSolver. :: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + In PySide(2), loadUi does not exist, so we implement it + + `_UiLoader` is adapted from the qtpy project, which was further influenced + by qt-helpers which was released under a 3-clause BSD license which in turn + is based on a solution at: + + - https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 + + The License for this code is as follows: + + qt-helpers - a common front-end to various Qt modules + + Copyright (c) 2015, Chris Beaumont and Thomas Robitaille + + All rights reserved. + + 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 Glue project 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 HOLDER 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. + + Which itself was based on the solution at + + https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 + + which was released under the MIT license: + + Copyright (c) 2011 Sebastian Wiesner + Modifications by Charl Botha + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files + (the "Software"),to deal in the Software without restriction, + including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + FindMaya (CMake) ---------------- diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 3ff1dd98e..346f21e09 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -63,19 +63,3 @@ add_custom_target( DEPENDS ${LEVMAR_EXTRACTED_FILE} COMMENT "Unpacking LevMar package..." ) - - -# Extract Qt.py -set(PY_SCRIPT "${CMAKE_SOURCE_DIR}/../scripts/get_qtpy.py") -add_custom_command( - OUTPUT ${QTPY_EXTRACTED_FILE} - COMMAND ${CMAKE_COMMAND} -E remove_directory ${QTPY_EXTRACTED_FILE} - COMMAND python ${PY_SCRIPT} ${ARCHIVES_DIR} ${WORKING_DIR} ${PATCHES_DIR} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS ${QTPY_DOWNLOAD_FILE} -) -add_custom_target( - qtpy_package ALL - DEPENDS ${QTPY_EXTRACTED_FILE} - COMMENT "Unpacking Qt.py package..." -) diff --git a/modules/mayaMatchMoveSolver_linux.mod b/modules/mayaMatchMoveSolver_linux.mod index 0461109ab..b70f844dd 100644 --- a/modules/mayaMatchMoveSolver_linux.mod +++ b/modules/mayaMatchMoveSolver_linux.mod @@ -13,5 +13,4 @@ MMSOLVER_DEFAULT_SOLVER = @DEFAULT_SOLVER@ MMSOLVER_DEBUG = 0 MAYA_CUSTOM_TEMPLATE_PATH +:= scripts/AETemplates PYTHONPATH +:= python -PYTHONPATH +:= python_qtpy [r] scripts: scripts diff --git a/modules/mayaMatchMoveSolver_windows.mod b/modules/mayaMatchMoveSolver_windows.mod index ddd9d16af..5bb1d16e3 100644 --- a/modules/mayaMatchMoveSolver_windows.mod +++ b/modules/mayaMatchMoveSolver_windows.mod @@ -14,5 +14,4 @@ MMSOLVER_DEBUG = 0 MAYA_CUSTOM_TEMPLATE_PATH +:= scripts/AETemplates PATH +:= lib PYTHONPATH +:= python -PYTHONPATH +:= python_qtpy [r] scripts: scripts diff --git a/python/mmSolver/tools/aboutwindow/ui/about_layout.py b/python/mmSolver/tools/aboutwindow/ui/about_layout.py index ef6771f67..f5cd476d8 100644 --- a/python/mmSolver/tools/aboutwindow/ui/about_layout.py +++ b/python/mmSolver/tools/aboutwindow/ui/about_layout.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.aboutwindow.lib.message as lib_msg diff --git a/python/mmSolver/tools/aboutwindow/ui/about_window.py b/python/mmSolver/tools/aboutwindow/ui/about_window.py index 9c73672e4..c528c7ea5 100644 --- a/python/mmSolver/tools/aboutwindow/ui/about_window.py +++ b/python/mmSolver/tools/aboutwindow/ui/about_window.py @@ -25,9 +25,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/attributebake/ui/attrbake_layout.py b/python/mmSolver/tools/attributebake/ui/attrbake_layout.py index 026aba891..6d42e2693 100644 --- a/python/mmSolver/tools/attributebake/ui/attrbake_layout.py +++ b/python/mmSolver/tools/attributebake/ui/attrbake_layout.py @@ -23,9 +23,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.configmaya as configmaya diff --git a/python/mmSolver/tools/attributebake/ui/attrbake_window.py b/python/mmSolver/tools/attributebake/ui/attrbake_window.py index 28f58a8da..5d921ec7e 100644 --- a/python/mmSolver/tools/attributebake/ui/attrbake_window.py +++ b/python/mmSolver/tools/attributebake/ui/attrbake_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/centertwodee/ui/centertwodee_layout.py b/python/mmSolver/tools/centertwodee/ui/centertwodee_layout.py index 093466f88..b120708ff 100644 --- a/python/mmSolver/tools/centertwodee/ui/centertwodee_layout.py +++ b/python/mmSolver/tools/centertwodee/ui/centertwodee_layout.py @@ -23,8 +23,8 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets -import Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore import mmSolver.logger import mmSolver.tools.centertwodee.ui.ui_centertwodee_layout as ui_centertwodee_layout diff --git a/python/mmSolver/tools/centertwodee/ui/centertwodee_window.py b/python/mmSolver/tools/centertwodee/ui/centertwodee_window.py index bb4b6a898..fda27016c 100644 --- a/python/mmSolver/tools/centertwodee/ui/centertwodee_window.py +++ b/python/mmSolver/tools/centertwodee/ui/centertwodee_window.py @@ -29,8 +29,8 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/channelsen/ui/channelsen_layout.py b/python/mmSolver/tools/channelsen/ui/channelsen_layout.py index 6346bf7a6..dff797868 100644 --- a/python/mmSolver/tools/channelsen/ui/channelsen_layout.py +++ b/python/mmSolver/tools/channelsen/ui/channelsen_layout.py @@ -23,7 +23,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.channelsen.ui.ui_channelsen_layout as ui_channelsen_layout diff --git a/python/mmSolver/tools/channelsen/ui/channelsen_window.py b/python/mmSolver/tools/channelsen/ui/channelsen_window.py index be72dbcea..6865438f7 100644 --- a/python/mmSolver/tools/channelsen/ui/channelsen_window.py +++ b/python/mmSolver/tools/channelsen/ui/channelsen_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/copypastecamera/tool.py b/python/mmSolver/tools/copypastecamera/tool.py index 7df15d252..36192254f 100644 --- a/python/mmSolver/tools/copypastecamera/tool.py +++ b/python/mmSolver/tools/copypastecamera/tool.py @@ -32,7 +32,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtGui as QtGui import mmSolver.utils.time as time_utils import mmSolver.utils.camera as camera_utils diff --git a/python/mmSolver/tools/createcontroller2/ui/createcontroller_layout.py b/python/mmSolver/tools/createcontroller2/ui/createcontroller_layout.py index 0e047289d..4f7b6bd39 100644 --- a/python/mmSolver/tools/createcontroller2/ui/createcontroller_layout.py +++ b/python/mmSolver/tools/createcontroller2/ui/createcontroller_layout.py @@ -23,7 +23,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtWidgets as QtWidgets import maya.cmds as cmds diff --git a/python/mmSolver/tools/createcontroller2/ui/createcontroller_window.py b/python/mmSolver/tools/createcontroller2/ui/createcontroller_window.py index dfe96d687..41466f621 100644 --- a/python/mmSolver/tools/createcontroller2/ui/createcontroller_window.py +++ b/python/mmSolver/tools/createcontroller2/ui/createcontroller_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/loadmarker/ui/loadmarker_layout.py b/python/mmSolver/tools/loadmarker/ui/loadmarker_layout.py index dd39c26de..ceb06556f 100644 --- a/python/mmSolver/tools/loadmarker/ui/loadmarker_layout.py +++ b/python/mmSolver/tools/loadmarker/ui/loadmarker_layout.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uimodels as uimodels diff --git a/python/mmSolver/tools/loadmarker/ui/loadmarker_window.py b/python/mmSolver/tools/loadmarker/ui/loadmarker_window.py index 057f121a3..9703458e8 100644 --- a/python/mmSolver/tools/loadmarker/ui/loadmarker_window.py +++ b/python/mmSolver/tools/loadmarker/ui/loadmarker_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/raycastmarker/ui/raycastmarker_layout.py b/python/mmSolver/tools/raycastmarker/ui/raycastmarker_layout.py index 45ebac5f8..91de6d897 100644 --- a/python/mmSolver/tools/raycastmarker/ui/raycastmarker_layout.py +++ b/python/mmSolver/tools/raycastmarker/ui/raycastmarker_layout.py @@ -23,7 +23,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtWidgets as QtWidgets import maya.cmds diff --git a/python/mmSolver/tools/raycastmarker/ui/raycastmarker_window.py b/python/mmSolver/tools/raycastmarker/ui/raycastmarker_window.py index 489c1b426..a5dc285d4 100644 --- a/python/mmSolver/tools/raycastmarker/ui/raycastmarker_window.py +++ b/python/mmSolver/tools/raycastmarker/ui/raycastmarker_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_layout.py b/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_layout.py index d422694fa..16bce58d3 100644 --- a/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_layout.py +++ b/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_layout.py @@ -29,7 +29,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.config as config_utils diff --git a/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_window.py b/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_window.py index b7e0794be..681c8938b 100644 --- a/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_window.py +++ b/python/mmSolver/tools/removesolvernodes/ui/removesolvernodes_window.py @@ -18,8 +18,8 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets import maya.cmds diff --git a/python/mmSolver/tools/screenspacerigbake/tool.py b/python/mmSolver/tools/screenspacerigbake/tool.py index b89719b58..aef439120 100644 --- a/python/mmSolver/tools/screenspacerigbake/tool.py +++ b/python/mmSolver/tools/screenspacerigbake/tool.py @@ -19,9 +19,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import maya.OpenMaya as om import maya.OpenMayaUI as omui diff --git a/python/mmSolver/tools/setattributedetails/ui/dialog.py b/python/mmSolver/tools/setattributedetails/ui/dialog.py index 82e9c8a99..b39e47f11 100644 --- a/python/mmSolver/tools/setattributedetails/ui/dialog.py +++ b/python/mmSolver/tools/setattributedetails/ui/dialog.py @@ -47,10 +47,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_layout.py b/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_layout.py index abec7d677..6d784404d 100644 --- a/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_layout.py +++ b/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_layout.py @@ -23,7 +23,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.smoothkeyframes.ui.ui_smoothkeys_layout as ui_smoothkeys_layout diff --git a/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_window.py b/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_window.py index 8ca5be9f1..e604cd2a5 100644 --- a/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_window.py +++ b/python/mmSolver/tools/smoothkeyframes/ui/smoothkeys_window.py @@ -28,9 +28,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/ui/attr_nodes.py b/python/mmSolver/tools/solver/ui/attr_nodes.py index 008accc1e..c41b5f786 100644 --- a/python/mmSolver/tools/solver/ui/attr_nodes.py +++ b/python/mmSolver/tools/solver/ui/attr_nodes.py @@ -24,7 +24,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtCore as QtCore import mmSolver.logger import mmSolver.api as mmapi diff --git a/python/mmSolver/tools/solver/ui/object_nodes.py b/python/mmSolver/tools/solver/ui/object_nodes.py index 0a91fcefb..a22ffe64b 100644 --- a/python/mmSolver/tools/solver/ui/object_nodes.py +++ b/python/mmSolver/tools/solver/ui/object_nodes.py @@ -22,8 +22,8 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui import mmSolver.logger import mmSolver.api as mmapi diff --git a/python/mmSolver/tools/solver/ui/solver_layout.py b/python/mmSolver/tools/solver/ui/solver_layout.py index 5451a4106..f1386945b 100644 --- a/python/mmSolver/tools/solver/ui/solver_layout.py +++ b/python/mmSolver/tools/solver/ui/solver_layout.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/ui/solver_window.py b/python/mmSolver/tools/solver/ui/solver_window.py index 08063ce3e..8053704cb 100644 --- a/python/mmSolver/tools/solver/ui/solver_window.py +++ b/python/mmSolver/tools/solver/ui/solver_window.py @@ -28,10 +28,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.undo as undo_utils diff --git a/python/mmSolver/tools/solver/widget/attribute_treeview.py b/python/mmSolver/tools/solver/widget/attribute_treeview.py index 1b005fddc..c371cde32 100644 --- a/python/mmSolver/tools/solver/widget/attribute_treeview.py +++ b/python/mmSolver/tools/solver/widget/attribute_treeview.py @@ -22,10 +22,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger diff --git a/python/mmSolver/tools/solver/widget/attribute_widget.py b/python/mmSolver/tools/solver/widget/attribute_widget.py index cb20d8afb..8737f5380 100644 --- a/python/mmSolver/tools/solver/widget/attribute_widget.py +++ b/python/mmSolver/tools/solver/widget/attribute_widget.py @@ -24,10 +24,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/widget/collection_widget.py b/python/mmSolver/tools/solver/widget/collection_widget.py index b38f2bd34..57b102092 100644 --- a/python/mmSolver/tools/solver/widget/collection_widget.py +++ b/python/mmSolver/tools/solver/widget/collection_widget.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uimodels as uimodels diff --git a/python/mmSolver/tools/solver/widget/framerange_widget.py b/python/mmSolver/tools/solver/widget/framerange_widget.py index 12c556344..65d0756fc 100644 --- a/python/mmSolver/tools/solver/widget/framerange_widget.py +++ b/python/mmSolver/tools/solver/widget/framerange_widget.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.time as utils_time diff --git a/python/mmSolver/tools/solver/widget/nodebrowser_utils.py b/python/mmSolver/tools/solver/widget/nodebrowser_utils.py index 17673029b..ab903eae5 100644 --- a/python/mmSolver/tools/solver/widget/nodebrowser_utils.py +++ b/python/mmSolver/tools/solver/widget/nodebrowser_utils.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/widget/nodebrowser_widget.py b/python/mmSolver/tools/solver/widget/nodebrowser_widget.py index 9f7cf15e1..d05237b12 100644 --- a/python/mmSolver/tools/solver/widget/nodebrowser_widget.py +++ b/python/mmSolver/tools/solver/widget/nodebrowser_widget.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.solver.widget.ui_nodebrowser_widget as ui_nodebrowser_widget diff --git a/python/mmSolver/tools/solver/widget/object_treeview.py b/python/mmSolver/tools/solver/widget/object_treeview.py index 6a47ca68c..73ad8e76d 100644 --- a/python/mmSolver/tools/solver/widget/object_treeview.py +++ b/python/mmSolver/tools/solver/widget/object_treeview.py @@ -22,10 +22,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.tools.solver.ui.object_nodes as object_nodes import mmSolver.tools.solver.lib.maya_utils as lib_maya_utils diff --git a/python/mmSolver/tools/solver/widget/object_widget.py b/python/mmSolver/tools/solver/widget/object_widget.py index 2a0ae57bf..343d60e6d 100644 --- a/python/mmSolver/tools/solver/widget/object_widget.py +++ b/python/mmSolver/tools/solver/widget/object_widget.py @@ -24,10 +24,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/widget/rootframe_widget.py b/python/mmSolver/tools/solver/widget/rootframe_widget.py index 3b39e8dc0..110d40918 100644 --- a/python/mmSolver/tools/solver/widget/rootframe_widget.py +++ b/python/mmSolver/tools/solver/widget/rootframe_widget.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.time as utils_time diff --git a/python/mmSolver/tools/solver/widget/solver_basic_widget.py b/python/mmSolver/tools/solver/widget/solver_basic_widget.py index 840bfe0d0..007174f2f 100644 --- a/python/mmSolver/tools/solver/widget/solver_basic_widget.py +++ b/python/mmSolver/tools/solver/widget/solver_basic_widget.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.solver.lib.state as lib_state diff --git a/python/mmSolver/tools/solver/widget/solver_legacy_widget.py b/python/mmSolver/tools/solver/widget/solver_legacy_widget.py index 0b2107d37..b2fce0292 100644 --- a/python/mmSolver/tools/solver/widget/solver_legacy_widget.py +++ b/python/mmSolver/tools/solver/widget/solver_legacy_widget.py @@ -27,9 +27,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/solver/widget/solver_standard_widget.py b/python/mmSolver/tools/solver/widget/solver_standard_widget.py index a3f7cc2cf..6109931b6 100644 --- a/python/mmSolver/tools/solver/widget/solver_standard_widget.py +++ b/python/mmSolver/tools/solver/widget/solver_standard_widget.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.solver.lib.state as lib_state diff --git a/python/mmSolver/tools/solver/widget/solver_widget.py b/python/mmSolver/tools/solver/widget/solver_widget.py index a16ae0b3c..6b19c39bd 100644 --- a/python/mmSolver/tools/solver/widget/solver_widget.py +++ b/python/mmSolver/tools/solver/widget/solver_widget.py @@ -24,9 +24,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.api as mmapi diff --git a/python/mmSolver/tools/solver/widget/solverstate_widget.py b/python/mmSolver/tools/solver/widget/solverstate_widget.py index 26bbd8a30..5dd1b3567 100644 --- a/python/mmSolver/tools/solver/widget/solverstate_widget.py +++ b/python/mmSolver/tools/solver/widget/solverstate_widget.py @@ -25,9 +25,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/sysinfowindow/ui/sysinfo_layout.py b/python/mmSolver/tools/sysinfowindow/ui/sysinfo_layout.py index 6ff291d61..d0f70e606 100644 --- a/python/mmSolver/tools/sysinfowindow/ui/sysinfo_layout.py +++ b/python/mmSolver/tools/sysinfowindow/ui/sysinfo_layout.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.sysinfowindow.lib.message as lib_msg diff --git a/python/mmSolver/tools/sysinfowindow/ui/sysinfo_window.py b/python/mmSolver/tools/sysinfowindow/ui/sysinfo_window.py index 4767e0060..91f7e659b 100644 --- a/python/mmSolver/tools/sysinfowindow/ui/sysinfo_window.py +++ b/python/mmSolver/tools/sysinfowindow/ui/sysinfo_window.py @@ -25,9 +25,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/tools/userprefswindow/ui/pref_layout.py b/python/mmSolver/tools/userprefswindow/ui/pref_layout.py index 1a9a2e04c..98e0302a1 100644 --- a/python/mmSolver/tools/userprefswindow/ui/pref_layout.py +++ b/python/mmSolver/tools/userprefswindow/ui/pref_layout.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.tools.userpreferences.lib as userprefs_lib diff --git a/python/mmSolver/tools/userprefswindow/ui/pref_window.py b/python/mmSolver/tools/userprefswindow/ui/pref_window.py index 5070b483c..f1d7a50ab 100644 --- a/python/mmSolver/tools/userprefswindow/ui/pref_window.py +++ b/python/mmSolver/tools/userprefswindow/ui/pref_window.py @@ -22,9 +22,9 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.ui.uiutils as uiutils diff --git a/python/mmSolver/ui/Qt.py b/python/mmSolver/ui/Qt.py new file mode 100644 index 000000000..b1d51c4f2 --- /dev/null +++ b/python/mmSolver/ui/Qt.py @@ -0,0 +1,1923 @@ +"""Minimal Python 2 & 3 shim around all Qt bindings + +DOCUMENTATION + Qt.py was born in the film and visual effects industry to address + the growing need for the development of software capable of running + with more than one flavour of the Qt bindings for Python - PySide, + PySide2, PyQt4 and PyQt5. + + 1. Build for one, run with all + 2. Explicit is better than implicit + 3. Support co-existence + + Default resolution order: + - PySide2 + - PyQt5 + - PySide + - PyQt4 + + Usage: + >> import sys + >> from Qt import QtWidgets + >> app = QtWidgets.QApplication(sys.argv) + >> button = QtWidgets.QPushButton("Hello World") + >> button.show() + >> app.exec_() + + All members of PySide2 are mapped from other bindings, should they exist. + If no equivalent member exist, it is excluded from Qt.py and inaccessible. + The idea is to highlight members that exist across all supported binding, + and guarantee that code that runs on one binding runs on all others. + + For more details, visit https://github.com/mottosso/Qt.py + +LICENSE + + See end of file for license (MIT, BSD) information. + +""" + +import os +import sys +import types +import shutil +import importlib + + +__version__ = "1.2.0" + +# Enable support for `from Qt import *` +__all__ = [] + +# Flags from environment variables +QT_VERBOSE = bool(os.getenv("QT_VERBOSE")) +QT_PREFERRED_BINDING = os.getenv("QT_PREFERRED_BINDING", "") +QT_SIP_API_HINT = os.getenv("QT_SIP_API_HINT") + +# Reference to Qt.py +Qt = sys.modules[__name__] +Qt.QtCompat = types.ModuleType("QtCompat") + +try: + long +except NameError: + # Python 3 compatibility + long = int + + +"""Common members of all bindings + +This is where each member of Qt.py is explicitly defined. +It is based on a "lowest common denominator" of all bindings; +including members found in each of the 4 bindings. + +The "_common_members" dictionary is generated using the +build_membership.sh script. + +""" + +_common_members = { + "QtCore": [ + "QAbstractAnimation", + "QAbstractEventDispatcher", + "QAbstractItemModel", + "QAbstractListModel", + "QAbstractState", + "QAbstractTableModel", + "QAbstractTransition", + "QAnimationGroup", + "QBasicTimer", + "QBitArray", + "QBuffer", + "QByteArray", + "QByteArrayMatcher", + "QChildEvent", + "QCoreApplication", + "QCryptographicHash", + "QDataStream", + "QDate", + "QDateTime", + "QDir", + "QDirIterator", + "QDynamicPropertyChangeEvent", + "QEasingCurve", + "QElapsedTimer", + "QEvent", + "QEventLoop", + "QEventTransition", + "QFile", + "QFileInfo", + "QFileSystemWatcher", + "QFinalState", + "QGenericArgument", + "QGenericReturnArgument", + "QHistoryState", + "QItemSelectionRange", + "QIODevice", + "QLibraryInfo", + "QLine", + "QLineF", + "QLocale", + "QMargins", + "QMetaClassInfo", + "QMetaEnum", + "QMetaMethod", + "QMetaObject", + "QMetaProperty", + "QMimeData", + "QModelIndex", + "QMutex", + "QMutexLocker", + "QObject", + "QParallelAnimationGroup", + "QPauseAnimation", + "QPersistentModelIndex", + "QPluginLoader", + "QPoint", + "QPointF", + "QProcess", + "QProcessEnvironment", + "QPropertyAnimation", + "QReadLocker", + "QReadWriteLock", + "QRect", + "QRectF", + "QRegExp", + "QResource", + "QRunnable", + "QSemaphore", + "QSequentialAnimationGroup", + "QSettings", + "QSignalMapper", + "QSignalTransition", + "QSize", + "QSizeF", + "QSocketNotifier", + "QState", + "QStateMachine", + "QSysInfo", + "QSystemSemaphore", + "QT_TRANSLATE_NOOP", + "QT_TR_NOOP", + "QT_TR_NOOP_UTF8", + "QTemporaryFile", + "QTextBoundaryFinder", + "QTextCodec", + "QTextDecoder", + "QTextEncoder", + "QTextStream", + "QTextStreamManipulator", + "QThread", + "QThreadPool", + "QTime", + "QTimeLine", + "QTimer", + "QTimerEvent", + "QTranslator", + "QUrl", + "QVariantAnimation", + "QWaitCondition", + "QWriteLocker", + "QXmlStreamAttribute", + "QXmlStreamAttributes", + "QXmlStreamEntityDeclaration", + "QXmlStreamEntityResolver", + "QXmlStreamNamespaceDeclaration", + "QXmlStreamNotationDeclaration", + "QXmlStreamReader", + "QXmlStreamWriter", + "Qt", + "QtCriticalMsg", + "QtDebugMsg", + "QtFatalMsg", + "QtMsgType", + "QtSystemMsg", + "QtWarningMsg", + "qAbs", + "qAddPostRoutine", + "qChecksum", + "qCritical", + "qDebug", + "qFatal", + "qFuzzyCompare", + "qIsFinite", + "qIsInf", + "qIsNaN", + "qIsNull", + "qRegisterResourceData", + "qUnregisterResourceData", + "qVersion", + "qWarning", + "qrand", + "qsrand" + ], + "QtGui": [ + "QAbstractTextDocumentLayout", + "QActionEvent", + "QBitmap", + "QBrush", + "QClipboard", + "QCloseEvent", + "QColor", + "QConicalGradient", + "QContextMenuEvent", + "QCursor", + "QDesktopServices", + "QDoubleValidator", + "QDrag", + "QDragEnterEvent", + "QDragLeaveEvent", + "QDragMoveEvent", + "QDropEvent", + "QFileOpenEvent", + "QFocusEvent", + "QFont", + "QFontDatabase", + "QFontInfo", + "QFontMetrics", + "QFontMetricsF", + "QGradient", + "QHelpEvent", + "QHideEvent", + "QHoverEvent", + "QIcon", + "QIconDragEvent", + "QIconEngine", + "QImage", + "QImageIOHandler", + "QImageReader", + "QImageWriter", + "QInputEvent", + "QInputMethodEvent", + "QIntValidator", + "QKeyEvent", + "QKeySequence", + "QLinearGradient", + "QMatrix2x2", + "QMatrix2x3", + "QMatrix2x4", + "QMatrix3x2", + "QMatrix3x3", + "QMatrix3x4", + "QMatrix4x2", + "QMatrix4x3", + "QMatrix4x4", + "QMouseEvent", + "QMoveEvent", + "QMovie", + "QPaintDevice", + "QPaintEngine", + "QPaintEngineState", + "QPaintEvent", + "QPainter", + "QPainterPath", + "QPainterPathStroker", + "QPalette", + "QPen", + "QPicture", + "QPictureIO", + "QPixmap", + "QPixmapCache", + "QPolygon", + "QPolygonF", + "QQuaternion", + "QRadialGradient", + "QRegExpValidator", + "QRegion", + "QResizeEvent", + "QSessionManager", + "QShortcutEvent", + "QShowEvent", + "QStandardItem", + "QStandardItemModel", + "QStatusTipEvent", + "QSyntaxHighlighter", + "QTabletEvent", + "QTextBlock", + "QTextBlockFormat", + "QTextBlockGroup", + "QTextBlockUserData", + "QTextCharFormat", + "QTextCursor", + "QTextDocument", + "QTextDocumentFragment", + "QTextFormat", + "QTextFragment", + "QTextFrame", + "QTextFrameFormat", + "QTextImageFormat", + "QTextInlineObject", + "QTextItem", + "QTextLayout", + "QTextLength", + "QTextLine", + "QTextList", + "QTextListFormat", + "QTextObject", + "QTextObjectInterface", + "QTextOption", + "QTextTable", + "QTextTableCell", + "QTextTableCellFormat", + "QTextTableFormat", + "QTouchEvent", + "QTransform", + "QValidator", + "QVector2D", + "QVector3D", + "QVector4D", + "QWhatsThisClickedEvent", + "QWheelEvent", + "QWindowStateChangeEvent", + "qAlpha", + "qBlue", + "qGray", + "qGreen", + "qIsGray", + "qRed", + "qRgb", + "qRgba" + ], + "QtHelp": [ + "QHelpContentItem", + "QHelpContentModel", + "QHelpContentWidget", + "QHelpEngine", + "QHelpEngineCore", + "QHelpIndexModel", + "QHelpIndexWidget", + "QHelpSearchEngine", + "QHelpSearchQuery", + "QHelpSearchQueryWidget", + "QHelpSearchResultWidget" + ], + "QtMultimedia": [ + "QAbstractVideoBuffer", + "QAbstractVideoSurface", + "QAudio", + "QAudioDeviceInfo", + "QAudioFormat", + "QAudioInput", + "QAudioOutput", + "QVideoFrame", + "QVideoSurfaceFormat" + ], + "QtNetwork": [ + "QAbstractNetworkCache", + "QAbstractSocket", + "QAuthenticator", + "QHostAddress", + "QHostInfo", + "QLocalServer", + "QLocalSocket", + "QNetworkAccessManager", + "QNetworkAddressEntry", + "QNetworkCacheMetaData", + "QNetworkConfiguration", + "QNetworkConfigurationManager", + "QNetworkCookie", + "QNetworkCookieJar", + "QNetworkDiskCache", + "QNetworkInterface", + "QNetworkProxy", + "QNetworkProxyFactory", + "QNetworkProxyQuery", + "QNetworkReply", + "QNetworkRequest", + "QNetworkSession", + "QSsl", + "QTcpServer", + "QTcpSocket", + "QUdpSocket" + ], + "QtOpenGL": [ + "QGL", + "QGLContext", + "QGLFormat", + "QGLWidget" + ], + "QtPrintSupport": [ + "QAbstractPrintDialog", + "QPageSetupDialog", + "QPrintDialog", + "QPrintEngine", + "QPrintPreviewDialog", + "QPrintPreviewWidget", + "QPrinter", + "QPrinterInfo" + ], + "QtSql": [ + "QSql", + "QSqlDatabase", + "QSqlDriver", + "QSqlDriverCreatorBase", + "QSqlError", + "QSqlField", + "QSqlIndex", + "QSqlQuery", + "QSqlQueryModel", + "QSqlRecord", + "QSqlRelation", + "QSqlRelationalDelegate", + "QSqlRelationalTableModel", + "QSqlResult", + "QSqlTableModel" + ], + "QtSvg": [ + "QGraphicsSvgItem", + "QSvgGenerator", + "QSvgRenderer", + "QSvgWidget" + ], + "QtTest": [ + "QTest" + ], + "QtWidgets": [ + "QAbstractButton", + "QAbstractGraphicsShapeItem", + "QAbstractItemDelegate", + "QAbstractItemView", + "QAbstractScrollArea", + "QAbstractSlider", + "QAbstractSpinBox", + "QAction", + "QActionGroup", + "QApplication", + "QBoxLayout", + "QButtonGroup", + "QCalendarWidget", + "QCheckBox", + "QColorDialog", + "QColumnView", + "QComboBox", + "QCommandLinkButton", + "QCommonStyle", + "QCompleter", + "QDataWidgetMapper", + "QDateEdit", + "QDateTimeEdit", + "QDesktopWidget", + "QDial", + "QDialog", + "QDialogButtonBox", + "QDirModel", + "QDockWidget", + "QDoubleSpinBox", + "QErrorMessage", + "QFileDialog", + "QFileIconProvider", + "QFileSystemModel", + "QFocusFrame", + "QFontComboBox", + "QFontDialog", + "QFormLayout", + "QFrame", + "QGesture", + "QGestureEvent", + "QGestureRecognizer", + "QGraphicsAnchor", + "QGraphicsAnchorLayout", + "QGraphicsBlurEffect", + "QGraphicsColorizeEffect", + "QGraphicsDropShadowEffect", + "QGraphicsEffect", + "QGraphicsEllipseItem", + "QGraphicsGridLayout", + "QGraphicsItem", + "QGraphicsItemGroup", + "QGraphicsLayout", + "QGraphicsLayoutItem", + "QGraphicsLineItem", + "QGraphicsLinearLayout", + "QGraphicsObject", + "QGraphicsOpacityEffect", + "QGraphicsPathItem", + "QGraphicsPixmapItem", + "QGraphicsPolygonItem", + "QGraphicsProxyWidget", + "QGraphicsRectItem", + "QGraphicsRotation", + "QGraphicsScale", + "QGraphicsScene", + "QGraphicsSceneContextMenuEvent", + "QGraphicsSceneDragDropEvent", + "QGraphicsSceneEvent", + "QGraphicsSceneHelpEvent", + "QGraphicsSceneHoverEvent", + "QGraphicsSceneMouseEvent", + "QGraphicsSceneMoveEvent", + "QGraphicsSceneResizeEvent", + "QGraphicsSceneWheelEvent", + "QGraphicsSimpleTextItem", + "QGraphicsTextItem", + "QGraphicsTransform", + "QGraphicsView", + "QGraphicsWidget", + "QGridLayout", + "QGroupBox", + "QHBoxLayout", + "QHeaderView", + "QInputDialog", + "QItemDelegate", + "QItemEditorCreatorBase", + "QItemEditorFactory", + "QKeyEventTransition", + "QLCDNumber", + "QLabel", + "QLayout", + "QLayoutItem", + "QLineEdit", + "QListView", + "QListWidget", + "QListWidgetItem", + "QMainWindow", + "QMdiArea", + "QMdiSubWindow", + "QMenu", + "QMenuBar", + "QMessageBox", + "QMouseEventTransition", + "QPanGesture", + "QPinchGesture", + "QPlainTextDocumentLayout", + "QPlainTextEdit", + "QProgressBar", + "QProgressDialog", + "QPushButton", + "QRadioButton", + "QRubberBand", + "QScrollArea", + "QScrollBar", + "QShortcut", + "QSizeGrip", + "QSizePolicy", + "QSlider", + "QSpacerItem", + "QSpinBox", + "QSplashScreen", + "QSplitter", + "QSplitterHandle", + "QStackedLayout", + "QStackedWidget", + "QStatusBar", + "QStyle", + "QStyleFactory", + "QStyleHintReturn", + "QStyleHintReturnMask", + "QStyleHintReturnVariant", + "QStyleOption", + "QStyleOptionButton", + "QStyleOptionComboBox", + "QStyleOptionComplex", + "QStyleOptionDockWidget", + "QStyleOptionFocusRect", + "QStyleOptionFrame", + "QStyleOptionGraphicsItem", + "QStyleOptionGroupBox", + "QStyleOptionHeader", + "QStyleOptionMenuItem", + "QStyleOptionProgressBar", + "QStyleOptionRubberBand", + "QStyleOptionSizeGrip", + "QStyleOptionSlider", + "QStyleOptionSpinBox", + "QStyleOptionTab", + "QStyleOptionTabBarBase", + "QStyleOptionTabWidgetFrame", + "QStyleOptionTitleBar", + "QStyleOptionToolBar", + "QStyleOptionToolBox", + "QStyleOptionToolButton", + "QStyleOptionViewItem", + "QStylePainter", + "QStyledItemDelegate", + "QSwipeGesture", + "QSystemTrayIcon", + "QTabBar", + "QTabWidget", + "QTableView", + "QTableWidget", + "QTableWidgetItem", + "QTableWidgetSelectionRange", + "QTapAndHoldGesture", + "QTapGesture", + "QTextBrowser", + "QTextEdit", + "QTimeEdit", + "QToolBar", + "QToolBox", + "QToolButton", + "QToolTip", + "QTreeView", + "QTreeWidget", + "QTreeWidgetItem", + "QTreeWidgetItemIterator", + "QUndoCommand", + "QUndoGroup", + "QUndoStack", + "QUndoView", + "QVBoxLayout", + "QWhatsThis", + "QWidget", + "QWidgetAction", + "QWidgetItem", + "QWizard", + "QWizardPage" + ], + "QtX11Extras": [ + "QX11Info" + ], + "QtXml": [ + "QDomAttr", + "QDomCDATASection", + "QDomCharacterData", + "QDomComment", + "QDomDocument", + "QDomDocumentFragment", + "QDomDocumentType", + "QDomElement", + "QDomEntity", + "QDomEntityReference", + "QDomImplementation", + "QDomNamedNodeMap", + "QDomNode", + "QDomNodeList", + "QDomNotation", + "QDomProcessingInstruction", + "QDomText", + "QXmlAttributes", + "QXmlContentHandler", + "QXmlDTDHandler", + "QXmlDeclHandler", + "QXmlDefaultHandler", + "QXmlEntityResolver", + "QXmlErrorHandler", + "QXmlInputSource", + "QXmlLexicalHandler", + "QXmlLocator", + "QXmlNamespaceSupport", + "QXmlParseException", + "QXmlReader", + "QXmlSimpleReader" + ], + "QtXmlPatterns": [ + "QAbstractMessageHandler", + "QAbstractUriResolver", + "QAbstractXmlNodeModel", + "QAbstractXmlReceiver", + "QSourceLocation", + "QXmlFormatter", + "QXmlItem", + "QXmlName", + "QXmlNamePool", + "QXmlNodeModelIndex", + "QXmlQuery", + "QXmlResultItems", + "QXmlSchema", + "QXmlSchemaValidator", + "QXmlSerializer" + ] +} + + +def _qInstallMessageHandler(handler): + """Install a message handler that works in all bindings + + Args: + handler: A function that takes 3 arguments, or None + """ + def messageOutputHandler(*args): + # In Qt4 bindings, message handlers are passed 2 arguments + # In Qt5 bindings, message handlers are passed 3 arguments + # The first argument is a QtMsgType + # The last argument is the message to be printed + # The Middle argument (if passed) is a QMessageLogContext + if len(args) == 3: + msgType, logContext, msg = args + elif len(args) == 2: + msgType, msg = args + logContext = None + else: + raise TypeError( + "handler expected 2 or 3 arguments, got {0}".format(len(args))) + + if isinstance(msg, bytes): + # In python 3, some bindings pass a bytestring, which cannot be + # used elsewhere. Decoding a python 2 or 3 bytestring object will + # consistently return a unicode object. + msg = msg.decode() + + handler(msgType, logContext, msg) + + passObject = messageOutputHandler if handler else handler + if Qt.IsPySide or Qt.IsPyQt4: + return Qt._QtCore.qInstallMsgHandler(passObject) + elif Qt.IsPySide2 or Qt.IsPyQt5: + return Qt._QtCore.qInstallMessageHandler(passObject) + + +def _getcpppointer(object): + if hasattr(Qt, "_shiboken2"): + return getattr(Qt, "_shiboken2").getCppPointer(object)[0] + elif hasattr(Qt, "_shiboken"): + return getattr(Qt, "_shiboken").getCppPointer(object)[0] + elif hasattr(Qt, "_sip"): + return getattr(Qt, "_sip").unwrapinstance(object) + raise AttributeError("'module' has no attribute 'getCppPointer'") + + +def _wrapinstance(ptr, base=None): + """Enable implicit cast of pointer to most suitable class + + This behaviour is available in sip per default. + + Based on http://nathanhorne.com/pyqtpyside-wrap-instance + + Usage: + This mechanism kicks in under these circumstances. + 1. Qt.py is using PySide 1 or 2. + 2. A `base` argument is not provided. + + See :func:`QtCompat.wrapInstance()` + + Arguments: + ptr (long): Pointer to QObject in memory + base (QObject, optional): Base class to wrap with. Defaults to QObject, + which should handle anything. + + """ + + assert isinstance(ptr, long), "Argument 'ptr' must be of type " + assert (base is None) or issubclass(base, Qt.QtCore.QObject), ( + "Argument 'base' must be of type ") + + if Qt.IsPyQt4 or Qt.IsPyQt5: + func = getattr(Qt, "_sip").wrapinstance + elif Qt.IsPySide2: + func = getattr(Qt, "_shiboken2").wrapInstance + elif Qt.IsPySide: + func = getattr(Qt, "_shiboken").wrapInstance + else: + raise AttributeError("'module' has no attribute 'wrapInstance'") + + if base is None: + q_object = func(long(ptr), Qt.QtCore.QObject) + meta_object = q_object.metaObject() + class_name = meta_object.className() + super_class_name = meta_object.superClass().className() + + if hasattr(Qt.QtWidgets, class_name): + base = getattr(Qt.QtWidgets, class_name) + + elif hasattr(Qt.QtWidgets, super_class_name): + base = getattr(Qt.QtWidgets, super_class_name) + + else: + base = Qt.QtCore.QObject + + return func(long(ptr), base) + + +def _isvalid(object): + """Check if the object is valid to use in Python runtime. + + Usage: + See :func:`QtCompat.isValid()` + + Arguments: + object (QObject): QObject to check the validity of. + + """ + + assert isinstance(object, Qt.QtCore.QObject) + + if hasattr(Qt, "_shiboken2"): + return getattr(Qt, "_shiboken2").isValid(object) + + elif hasattr(Qt, "_shiboken"): + return getattr(Qt, "_shiboken").isValid(object) + + elif hasattr(Qt, "_sip"): + return not getattr(Qt, "_sip").isdeleted(object) + + else: + raise AttributeError("'module' has no attribute isValid") + + +def _translate(context, sourceText, *args): + # In Qt4 bindings, translate can be passed 2 or 3 arguments + # In Qt5 bindings, translate can be passed 2 arguments + # The first argument is disambiguation[str] + # The last argument is n[int] + # The middle argument can be encoding[QtCore.QCoreApplication.Encoding] + if len(args) == 3: + disambiguation, encoding, n = args + elif len(args) == 2: + disambiguation, n = args + encoding = None + else: + raise TypeError( + "Expected 4 or 5 arguments, got {0}.".format(len(args) + 2)) + + if hasattr(Qt.QtCore, "QCoreApplication"): + app = getattr(Qt.QtCore, "QCoreApplication") + else: + raise NotImplementedError( + "Missing QCoreApplication implementation for {binding}".format( + binding=Qt.__binding__, + ) + ) + if Qt.__binding__ in ("PySide2", "PyQt5"): + sanitized_args = [context, sourceText, disambiguation, n] + else: + sanitized_args = [ + context, + sourceText, + disambiguation, + encoding or app.CodecForTr, + n + ] + return app.translate(*sanitized_args) + + +def _loadUi(uifile, baseinstance=None): + """Dynamically load a user interface from the given `uifile` + + This function calls `uic.loadUi` if using PyQt bindings, + else it implements a comparable binding for PySide. + + Documentation: + http://pyqt.sourceforge.net/Docs/PyQt5/designer.html#PyQt5.uic.loadUi + + Arguments: + uifile (str): Absolute path to Qt Designer file. + baseinstance (QWidget): Instantiated QWidget or subclass thereof + + Return: + baseinstance if `baseinstance` is not `None`. Otherwise + return the newly created instance of the user interface. + + """ + if hasattr(Qt, "_uic"): + return Qt._uic.loadUi(uifile, baseinstance) + + elif hasattr(Qt, "_QtUiTools"): + # Implement `PyQt5.uic.loadUi` for PySide(2) + + class _UiLoader(Qt._QtUiTools.QUiLoader): + """Create the user interface in a base instance. + + Unlike `Qt._QtUiTools.QUiLoader` itself this class does not + create a new instance of the top-level widget, but creates the user + interface in an existing instance of the top-level class if needed. + + This mimics the behaviour of `PyQt5.uic.loadUi`. + + """ + + def __init__(self, baseinstance): + super(_UiLoader, self).__init__(baseinstance) + self.baseinstance = baseinstance + self.custom_widgets = {} + + def _loadCustomWidgets(self, etree): + """ + Workaround to pyside-77 bug. + + From QUiLoader doc we should use registerCustomWidget method. + But this causes a segfault on some platforms. + + Instead we fetch from customwidgets DOM node the python class + objects. Then we can directly use them in createWidget method. + """ + + def headerToModule(header): + """ + Translate a header file to python module path + foo/bar.h => foo.bar + """ + # Remove header extension + module = os.path.splitext(header)[0] + + # Replace os separator by python module separator + return module.replace("/", ".").replace("\\", ".") + + custom_widgets = etree.find("customwidgets") + + if custom_widgets is None: + return + + for custom_widget in custom_widgets: + class_name = custom_widget.find("class").text + header = custom_widget.find("header").text + module = importlib.import_module(headerToModule(header)) + self.custom_widgets[class_name] = getattr(module, + class_name) + + def load(self, uifile, *args, **kwargs): + from xml.etree.ElementTree import ElementTree + + # For whatever reason, if this doesn't happen then + # reading an invalid or non-existing .ui file throws + # a RuntimeError. + etree = ElementTree() + etree.parse(uifile) + self._loadCustomWidgets(etree) + + widget = Qt._QtUiTools.QUiLoader.load( + self, uifile, *args, **kwargs) + + # Workaround for PySide 1.0.9, see issue #208 + widget.parentWidget() + + return widget + + def createWidget(self, class_name, parent=None, name=""): + """Called for each widget defined in ui file + + Overridden here to populate `baseinstance` instead. + + """ + + if parent is None and self.baseinstance: + # Supposed to create the top-level widget, + # return the base instance instead + return self.baseinstance + + # For some reason, Line is not in the list of available + # widgets, but works fine, so we have to special case it here. + if class_name in self.availableWidgets() + ["Line"]: + # Create a new widget for child widgets + widget = Qt._QtUiTools.QUiLoader.createWidget(self, + class_name, + parent, + name) + elif class_name in self.custom_widgets: + widget = self.custom_widgets[class_name](parent) + else: + raise Exception("Custom widget '%s' not supported" + % class_name) + + if self.baseinstance: + # Set an attribute for the new child widget on the base + # instance, just like PyQt5.uic.loadUi does. + setattr(self.baseinstance, name, widget) + + return widget + + widget = _UiLoader(baseinstance).load(uifile) + Qt.QtCore.QMetaObject.connectSlotsByName(widget) + + return widget + + else: + raise NotImplementedError("No implementation available for loadUi") + + +"""Misplaced members + +These members from the original submodule are misplaced relative PySide2 + +""" +_misplaced_members = { + "PySide2": { + "QtCore.QStringListModel": "QtCore.QStringListModel", + "QtGui.QStringListModel": "QtCore.QStringListModel", + "QtCore.Property": "QtCore.Property", + "QtCore.Signal": "QtCore.Signal", + "QtCore.Slot": "QtCore.Slot", + "QtCore.QAbstractProxyModel": "QtCore.QAbstractProxyModel", + "QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel", + "QtCore.QItemSelection": "QtCore.QItemSelection", + "QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel", + "QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange", + "QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi], + "shiboken2.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance], + "shiboken2.getCppPointer": ["QtCompat.getCppPointer", _getcpppointer], + "shiboken2.isValid": ["QtCompat.isValid", _isvalid], + "QtWidgets.qApp": "QtWidgets.QApplication.instance()", + "QtCore.QCoreApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtWidgets.QApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtCore.qInstallMessageHandler": [ + "QtCompat.qInstallMessageHandler", _qInstallMessageHandler + ], + }, + "PyQt5": { + "QtCore.pyqtProperty": "QtCore.Property", + "QtCore.pyqtSignal": "QtCore.Signal", + "QtCore.pyqtSlot": "QtCore.Slot", + "QtCore.QAbstractProxyModel": "QtCore.QAbstractProxyModel", + "QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel", + "QtCore.QStringListModel": "QtCore.QStringListModel", + "QtCore.QItemSelection": "QtCore.QItemSelection", + "QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel", + "QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange", + "uic.loadUi": ["QtCompat.loadUi", _loadUi], + "sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance], + "sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer], + "sip.isdeleted": ["QtCompat.isValid", _isvalid], + "QtWidgets.qApp": "QtWidgets.QApplication.instance()", + "QtCore.QCoreApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtWidgets.QApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtCore.qInstallMessageHandler": [ + "QtCompat.qInstallMessageHandler", _qInstallMessageHandler + ], + }, + "PySide": { + "QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel", + "QtGui.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel", + "QtGui.QStringListModel": "QtCore.QStringListModel", + "QtGui.QItemSelection": "QtCore.QItemSelection", + "QtGui.QItemSelectionModel": "QtCore.QItemSelectionModel", + "QtCore.Property": "QtCore.Property", + "QtCore.Signal": "QtCore.Signal", + "QtCore.Slot": "QtCore.Slot", + "QtGui.QItemSelectionRange": "QtCore.QItemSelectionRange", + "QtGui.QAbstractPrintDialog": "QtPrintSupport.QAbstractPrintDialog", + "QtGui.QPageSetupDialog": "QtPrintSupport.QPageSetupDialog", + "QtGui.QPrintDialog": "QtPrintSupport.QPrintDialog", + "QtGui.QPrintEngine": "QtPrintSupport.QPrintEngine", + "QtGui.QPrintPreviewDialog": "QtPrintSupport.QPrintPreviewDialog", + "QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget", + "QtGui.QPrinter": "QtPrintSupport.QPrinter", + "QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo", + "QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi], + "shiboken.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance], + "shiboken.unwrapInstance": ["QtCompat.getCppPointer", _getcpppointer], + "shiboken.isValid": ["QtCompat.isValid", _isvalid], + "QtGui.qApp": "QtWidgets.QApplication.instance()", + "QtCore.QCoreApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtGui.QApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtCore.qInstallMsgHandler": [ + "QtCompat.qInstallMessageHandler", _qInstallMessageHandler + ], + }, + "PyQt4": { + "QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel", + "QtGui.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel", + "QtGui.QItemSelection": "QtCore.QItemSelection", + "QtGui.QStringListModel": "QtCore.QStringListModel", + "QtGui.QItemSelectionModel": "QtCore.QItemSelectionModel", + "QtCore.pyqtProperty": "QtCore.Property", + "QtCore.pyqtSignal": "QtCore.Signal", + "QtCore.pyqtSlot": "QtCore.Slot", + "QtGui.QItemSelectionRange": "QtCore.QItemSelectionRange", + "QtGui.QAbstractPrintDialog": "QtPrintSupport.QAbstractPrintDialog", + "QtGui.QPageSetupDialog": "QtPrintSupport.QPageSetupDialog", + "QtGui.QPrintDialog": "QtPrintSupport.QPrintDialog", + "QtGui.QPrintEngine": "QtPrintSupport.QPrintEngine", + "QtGui.QPrintPreviewDialog": "QtPrintSupport.QPrintPreviewDialog", + "QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget", + "QtGui.QPrinter": "QtPrintSupport.QPrinter", + "QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo", + # "QtCore.pyqtSignature": "QtCore.Slot", + "uic.loadUi": ["QtCompat.loadUi", _loadUi], + "sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance], + "sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer], + "sip.isdeleted": ["QtCompat.isValid", _isvalid], + "QtCore.QString": "str", + "QtGui.qApp": "QtWidgets.QApplication.instance()", + "QtCore.QCoreApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtGui.QApplication.translate": [ + "QtCompat.translate", _translate + ], + "QtCore.qInstallMsgHandler": [ + "QtCompat.qInstallMessageHandler", _qInstallMessageHandler + ], + } +} + +""" Compatibility Members + +This dictionary is used to build Qt.QtCompat objects that provide a consistent +interface for obsolete members, and differences in binding return values. + +{ + "binding": { + "classname": { + "targetname": "binding_namespace", + } + } +} +""" +_compatibility_members = { + "PySide2": { + "QWidget": { + "grab": "QtWidgets.QWidget.grab", + }, + "QHeaderView": { + "sectionsClickable": "QtWidgets.QHeaderView.sectionsClickable", + "setSectionsClickable": + "QtWidgets.QHeaderView.setSectionsClickable", + "sectionResizeMode": "QtWidgets.QHeaderView.sectionResizeMode", + "setSectionResizeMode": + "QtWidgets.QHeaderView.setSectionResizeMode", + "sectionsMovable": "QtWidgets.QHeaderView.sectionsMovable", + "setSectionsMovable": "QtWidgets.QHeaderView.setSectionsMovable", + }, + "QFileDialog": { + "getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName", + "getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames", + "getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName", + }, + }, + "PyQt5": { + "QWidget": { + "grab": "QtWidgets.QWidget.grab", + }, + "QHeaderView": { + "sectionsClickable": "QtWidgets.QHeaderView.sectionsClickable", + "setSectionsClickable": + "QtWidgets.QHeaderView.setSectionsClickable", + "sectionResizeMode": "QtWidgets.QHeaderView.sectionResizeMode", + "setSectionResizeMode": + "QtWidgets.QHeaderView.setSectionResizeMode", + "sectionsMovable": "QtWidgets.QHeaderView.sectionsMovable", + "setSectionsMovable": "QtWidgets.QHeaderView.setSectionsMovable", + }, + "QFileDialog": { + "getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName", + "getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames", + "getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName", + }, + }, + "PySide": { + "QWidget": { + "grab": "QtWidgets.QPixmap.grabWidget", + }, + "QHeaderView": { + "sectionsClickable": "QtWidgets.QHeaderView.isClickable", + "setSectionsClickable": "QtWidgets.QHeaderView.setClickable", + "sectionResizeMode": "QtWidgets.QHeaderView.resizeMode", + "setSectionResizeMode": "QtWidgets.QHeaderView.setResizeMode", + "sectionsMovable": "QtWidgets.QHeaderView.isMovable", + "setSectionsMovable": "QtWidgets.QHeaderView.setMovable", + }, + "QFileDialog": { + "getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName", + "getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames", + "getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName", + }, + }, + "PyQt4": { + "QWidget": { + "grab": "QtWidgets.QPixmap.grabWidget", + }, + "QHeaderView": { + "sectionsClickable": "QtWidgets.QHeaderView.isClickable", + "setSectionsClickable": "QtWidgets.QHeaderView.setClickable", + "sectionResizeMode": "QtWidgets.QHeaderView.resizeMode", + "setSectionResizeMode": "QtWidgets.QHeaderView.setResizeMode", + "sectionsMovable": "QtWidgets.QHeaderView.isMovable", + "setSectionsMovable": "QtWidgets.QHeaderView.setMovable", + }, + "QFileDialog": { + "getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName", + "getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames", + "getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName", + }, + }, +} + + +def _apply_site_config(): + try: + import QtSiteConfig + except ImportError: + # If no QtSiteConfig module found, no modifications + # to _common_members are needed. + pass + else: + # Provide the ability to modify the dicts used to build Qt.py + if hasattr(QtSiteConfig, 'update_members'): + QtSiteConfig.update_members(_common_members) + + if hasattr(QtSiteConfig, 'update_misplaced_members'): + QtSiteConfig.update_misplaced_members(members=_misplaced_members) + + if hasattr(QtSiteConfig, 'update_compatibility_members'): + QtSiteConfig.update_compatibility_members( + members=_compatibility_members) + + +def _new_module(name): + return types.ModuleType(__name__ + "." + name) + + +def _import_sub_module(module, name): + """import_sub_module will mimic the function of importlib.import_module""" + module = __import__(module.__name__ + "." + name) + for level in name.split("."): + module = getattr(module, level) + return module + + +def _setup(module, extras): + """Install common submodules""" + + Qt.__binding__ = module.__name__ + + for name in list(_common_members) + extras: + try: + submodule = _import_sub_module( + module, name) + except ImportError: + try: + # For extra modules like sip and shiboken that may not be + # children of the binding. + submodule = __import__(name) + except ImportError: + continue + + setattr(Qt, "_" + name, submodule) + + if name not in extras: + # Store reference to original binding, + # but don't store speciality modules + # such as uic or QtUiTools + setattr(Qt, name, _new_module(name)) + + +def _reassign_misplaced_members(binding): + """Apply misplaced members from `binding` to Qt.py + + Arguments: + binding (dict): Misplaced members + + """ + + for src, dst in _misplaced_members[binding].items(): + dst_value = None + + src_parts = src.split(".") + src_module = src_parts[0] + src_member = None + if len(src_parts) > 1: + src_member = src_parts[1:] + + if isinstance(dst, (list, tuple)): + dst, dst_value = dst + + dst_parts = dst.split(".") + dst_module = dst_parts[0] + dst_member = None + if len(dst_parts) > 1: + dst_member = dst_parts[1] + + # Get the member we want to store in the namesapce. + if not dst_value: + try: + _part = getattr(Qt, "_" + src_module) + while src_member: + member = src_member.pop(0) + _part = getattr(_part, member) + dst_value = _part + except AttributeError: + # If the member we want to store in the namespace does not + # exist, there is no need to continue. This can happen if a + # request was made to rename a member that didn't exist, for + # example if QtWidgets isn't available on the target platform. + _log("Misplaced member has no source: {0}".format(src)) + continue + + try: + src_object = getattr(Qt, dst_module) + except AttributeError: + if dst_module not in _common_members: + # Only create the Qt parent module if its listed in + # _common_members. Without this check, if you remove QtCore + # from _common_members, the default _misplaced_members will add + # Qt.QtCore so it can add Signal, Slot, etc. + msg = 'Not creating missing member module "{m}" for "{c}"' + _log(msg.format(m=dst_module, c=dst_member)) + continue + # If the dst is valid but the Qt parent module does not exist + # then go ahead and create a new module to contain the member. + setattr(Qt, dst_module, _new_module(dst_module)) + src_object = getattr(Qt, dst_module) + # Enable direct import of the new module + sys.modules[__name__ + "." + dst_module] = src_object + + if not dst_value: + dst_value = getattr(Qt, "_" + src_module) + if src_member: + dst_value = getattr(dst_value, src_member) + + setattr( + src_object, + dst_member or dst_module, + dst_value + ) + + +def _build_compatibility_members(binding, decorators=None): + """Apply `binding` to QtCompat + + Arguments: + binding (str): Top level binding in _compatibility_members. + decorators (dict, optional): Provides the ability to decorate the + original Qt methods when needed by a binding. This can be used + to change the returned value to a standard value. The key should + be the classname, the value is a dict where the keys are the + target method names, and the values are the decorator functions. + + """ + + decorators = decorators or dict() + + # Allow optional site-level customization of the compatibility members. + # This method does not need to be implemented in QtSiteConfig. + try: + import QtSiteConfig + except ImportError: + pass + else: + if hasattr(QtSiteConfig, 'update_compatibility_decorators'): + QtSiteConfig.update_compatibility_decorators(binding, decorators) + + _QtCompat = type("QtCompat", (object,), {}) + + for classname, bindings in _compatibility_members[binding].items(): + attrs = {} + for target, binding in bindings.items(): + namespaces = binding.split('.') + try: + src_object = getattr(Qt, "_" + namespaces[0]) + except AttributeError as e: + _log("QtCompat: AttributeError: %s" % e) + # Skip reassignment of non-existing members. + # This can happen if a request was made to + # rename a member that didn't exist, for example + # if QtWidgets isn't available on the target platform. + continue + + # Walk down any remaining namespace getting the object assuming + # that if the first namespace exists the rest will exist. + for namespace in namespaces[1:]: + src_object = getattr(src_object, namespace) + + # decorate the Qt method if a decorator was provided. + if target in decorators.get(classname, []): + # staticmethod must be called on the decorated method to + # prevent a TypeError being raised when the decorated method + # is called. + src_object = staticmethod( + decorators[classname][target](src_object)) + + attrs[target] = src_object + + # Create the QtCompat class and install it into the namespace + compat_class = type(classname, (_QtCompat,), attrs) + setattr(Qt.QtCompat, classname, compat_class) + + +def _pyside2(): + """Initialise PySide2 + + These functions serve to test the existence of a binding + along with set it up in such a way that it aligns with + the final step; adding members from the original binding + to Qt.py + + """ + + import PySide2 as module + extras = ["QtUiTools"] + try: + try: + # Before merge of PySide and shiboken + import shiboken2 + except ImportError: + # After merge of PySide and shiboken, May 2017 + from PySide2 import shiboken2 + extras.append("shiboken2") + except ImportError: + pass + + _setup(module, extras) + Qt.__binding_version__ = module.__version__ + + if hasattr(Qt, "_shiboken2"): + Qt.QtCompat.wrapInstance = _wrapinstance + Qt.QtCompat.getCppPointer = _getcpppointer + Qt.QtCompat.delete = shiboken2.delete + + if hasattr(Qt, "_QtUiTools"): + Qt.QtCompat.loadUi = _loadUi + + if hasattr(Qt, "_QtCore"): + Qt.__qt_version__ = Qt._QtCore.qVersion() + Qt.QtCompat.dataChanged = ( + lambda self, topleft, bottomright, roles=None: + self.dataChanged.emit(topleft, bottomright, roles or []) + ) + + if hasattr(Qt, "_QtWidgets"): + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtWidgets.QHeaderView.setSectionResizeMode + + _reassign_misplaced_members("PySide2") + _build_compatibility_members("PySide2") + + +def _pyside(): + """Initialise PySide""" + + import PySide as module + extras = ["QtUiTools"] + try: + try: + # Before merge of PySide and shiboken + import shiboken + except ImportError: + # After merge of PySide and shiboken, May 2017 + from PySide import shiboken + extras.append("shiboken") + except ImportError: + pass + + _setup(module, extras) + Qt.__binding_version__ = module.__version__ + + if hasattr(Qt, "_shiboken"): + Qt.QtCompat.wrapInstance = _wrapinstance + Qt.QtCompat.getCppPointer = _getcpppointer + Qt.QtCompat.delete = shiboken.delete + + if hasattr(Qt, "_QtUiTools"): + Qt.QtCompat.loadUi = _loadUi + + if hasattr(Qt, "_QtGui"): + setattr(Qt, "QtWidgets", _new_module("QtWidgets")) + setattr(Qt, "_QtWidgets", Qt._QtGui) + if hasattr(Qt._QtGui, "QX11Info"): + setattr(Qt, "QtX11Extras", _new_module("QtX11Extras")) + Qt.QtX11Extras.QX11Info = Qt._QtGui.QX11Info + + Qt.QtCompat.setSectionResizeMode = Qt._QtGui.QHeaderView.setResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.__qt_version__ = Qt._QtCore.qVersion() + Qt.QtCompat.dataChanged = ( + lambda self, topleft, bottomright, roles=None: + self.dataChanged.emit(topleft, bottomright) + ) + + _reassign_misplaced_members("PySide") + _build_compatibility_members("PySide") + + +def _pyqt5(): + """Initialise PyQt5""" + + import PyQt5 as module + extras = ["uic"] + + try: + import sip + extras += ["sip"] + except ImportError: + + # Relevant to PyQt5 5.11 and above + try: + from PyQt5 import sip + extras += ["sip"] + except ImportError: + sip = None + + _setup(module, extras) + if hasattr(Qt, "_sip"): + Qt.QtCompat.wrapInstance = _wrapinstance + Qt.QtCompat.getCppPointer = _getcpppointer + Qt.QtCompat.delete = sip.delete + + if hasattr(Qt, "_uic"): + Qt.QtCompat.loadUi = _loadUi + + if hasattr(Qt, "_QtCore"): + Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR + Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR + Qt.QtCompat.dataChanged = ( + lambda self, topleft, bottomright, roles=None: + self.dataChanged.emit(topleft, bottomright, roles or []) + ) + + if hasattr(Qt, "_QtWidgets"): + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtWidgets.QHeaderView.setSectionResizeMode + + _reassign_misplaced_members("PyQt5") + _build_compatibility_members('PyQt5') + + +def _pyqt4(): + """Initialise PyQt4""" + + import sip + + # Validation of envivornment variable. Prevents an error if + # the variable is invalid since it's just a hint. + try: + hint = int(QT_SIP_API_HINT) + except TypeError: + hint = None # Variable was None, i.e. not set. + except ValueError: + raise ImportError("QT_SIP_API_HINT=%s must be a 1 or 2") + + for api in ("QString", + "QVariant", + "QDate", + "QDateTime", + "QTextStream", + "QTime", + "QUrl"): + try: + sip.setapi(api, hint or 2) + except AttributeError: + raise ImportError("PyQt4 < 4.6 isn't supported by Qt.py") + except ValueError: + actual = sip.getapi(api) + if not hint: + raise ImportError("API version already set to %d" % actual) + else: + # Having provided a hint indicates a soft constraint, one + # that doesn't throw an exception. + sys.stderr.write( + "Warning: API '%s' has already been set to %d.\n" + % (api, actual) + ) + + import PyQt4 as module + extras = ["uic"] + try: + import sip + extras.append(sip.__name__) + except ImportError: + sip = None + + _setup(module, extras) + if hasattr(Qt, "_sip"): + Qt.QtCompat.wrapInstance = _wrapinstance + Qt.QtCompat.getCppPointer = _getcpppointer + Qt.QtCompat.delete = sip.delete + + if hasattr(Qt, "_uic"): + Qt.QtCompat.loadUi = _loadUi + + if hasattr(Qt, "_QtGui"): + setattr(Qt, "QtWidgets", _new_module("QtWidgets")) + setattr(Qt, "_QtWidgets", Qt._QtGui) + if hasattr(Qt._QtGui, "QX11Info"): + setattr(Qt, "QtX11Extras", _new_module("QtX11Extras")) + Qt.QtX11Extras.QX11Info = Qt._QtGui.QX11Info + + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtGui.QHeaderView.setResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR + Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR + Qt.QtCompat.dataChanged = ( + lambda self, topleft, bottomright, roles=None: + self.dataChanged.emit(topleft, bottomright) + ) + + _reassign_misplaced_members("PyQt4") + + # QFileDialog QtCompat decorator + def _standardizeQFileDialog(some_function): + """Decorator that makes PyQt4 return conform to other bindings""" + def wrapper(*args, **kwargs): + ret = (some_function(*args, **kwargs)) + + # PyQt4 only returns the selected filename, force it to a + # standard return of the selected filename, and a empty string + # for the selected filter + return ret, '' + + wrapper.__doc__ = some_function.__doc__ + wrapper.__name__ = some_function.__name__ + + return wrapper + + decorators = { + "QFileDialog": { + "getOpenFileName": _standardizeQFileDialog, + "getOpenFileNames": _standardizeQFileDialog, + "getSaveFileName": _standardizeQFileDialog, + } + } + _build_compatibility_members('PyQt4', decorators) + + +def _none(): + """Internal option (used in installer)""" + + Mock = type("Mock", (), {"__getattr__": lambda Qt, attr: None}) + + Qt.__binding__ = "None" + Qt.__qt_version__ = "0.0.0" + Qt.__binding_version__ = "0.0.0" + Qt.QtCompat.loadUi = lambda uifile, baseinstance=None: None + Qt.QtCompat.setSectionResizeMode = lambda *args, **kwargs: None + + for submodule in _common_members.keys(): + setattr(Qt, submodule, Mock()) + setattr(Qt, "_" + submodule, Mock()) + + +def _log(text): + if QT_VERBOSE: + sys.stdout.write(text + "\n") + + +def _convert(lines): + """Convert compiled .ui file from PySide2 to Qt.py + + Arguments: + lines (list): Each line of of .ui file + + Usage: + >> with open("myui.py") as f: + .. lines = _convert(f.readlines()) + + """ + + def parse(line): + line = line.replace("from PySide2 import", "from Qt import QtCompat,") + line = line.replace("QtWidgets.QApplication.translate", + "QtCompat.translate") + if "QtCore.SIGNAL" in line: + raise NotImplementedError("QtCore.SIGNAL is missing from PyQt5 " + "and so Qt.py does not support it: you " + "should avoid defining signals inside " + "your ui files.") + return line + + parsed = list() + for line in lines: + line = parse(line) + parsed.append(line) + + return parsed + + +def _cli(args): + """Qt.py command-line interface""" + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--convert", + help="Path to compiled Python module, e.g. my_ui.py") + parser.add_argument("--compile", + help="Accept raw .ui file and compile with native " + "PySide2 compiler.") + parser.add_argument("--stdout", + help="Write to stdout instead of file", + action="store_true") + parser.add_argument("--stdin", + help="Read from stdin instead of file", + action="store_true") + + args = parser.parse_args(args) + + if args.stdout: + raise NotImplementedError("--stdout") + + if args.stdin: + raise NotImplementedError("--stdin") + + if args.compile: + raise NotImplementedError("--compile") + + if args.convert: + sys.stdout.write("#\n" + "# WARNING: --convert is an ALPHA feature.\n#\n" + "# See https://github.com/mottosso/Qt.py/pull/132\n" + "# for details.\n" + "#\n") + + # + # ------> Read + # + with open(args.convert) as f: + lines = _convert(f.readlines()) + + backup = "%s_backup%s" % os.path.splitext(args.convert) + sys.stdout.write("Creating \"%s\"..\n" % backup) + shutil.copy(args.convert, backup) + + # + # <------ Write + # + with open(args.convert, "w") as f: + f.write("".join(lines)) + + sys.stdout.write("Successfully converted \"%s\"\n" % args.convert) + + +def _install(): + # Default order (customise order and content via QT_PREFERRED_BINDING) + default_order = ("PySide2", "PyQt5", "PySide", "PyQt4") + preferred_order = list( + b for b in QT_PREFERRED_BINDING.split(os.pathsep) if b + ) + + order = preferred_order or default_order + + available = { + "PySide2": _pyside2, + "PyQt5": _pyqt5, + "PySide": _pyside, + "PyQt4": _pyqt4, + "None": _none + } + + _log("Order: '%s'" % "', '".join(order)) + + # Allow site-level customization of the available modules. + _apply_site_config() + + found_binding = False + for name in order: + _log("Trying %s" % name) + + try: + available[name]() + found_binding = True + break + + except ImportError as e: + _log("ImportError: %s" % e) + + except KeyError: + _log("ImportError: Preferred binding '%s' not found." % name) + + if not found_binding: + # If not binding were found, throw this error + raise ImportError("No Qt binding were found.") + + # Install individual members + for name, members in _common_members.items(): + try: + their_submodule = getattr(Qt, "_%s" % name) + except AttributeError: + continue + + our_submodule = getattr(Qt, name) + + # Enable import * + __all__.append(name) + + # Enable direct import of submodule, + # e.g. import Qt.QtCore + sys.modules[__name__ + "." + name] = our_submodule + + for member in members: + # Accept that a submodule may miss certain members. + try: + their_member = getattr(their_submodule, member) + except AttributeError: + _log("'%s.%s' was missing." % (name, member)) + continue + + setattr(our_submodule, member, their_member) + + # Enable direct import of QtCompat + sys.modules['Qt.QtCompat'] = Qt.QtCompat + + # Backwards compatibility + if hasattr(Qt.QtCompat, 'loadUi'): + Qt.QtCompat.load_ui = Qt.QtCompat.loadUi + + +_install() + +# Setup Binding Enum states +Qt.IsPySide2 = Qt.__binding__ == 'PySide2' +Qt.IsPyQt5 = Qt.__binding__ == 'PyQt5' +Qt.IsPySide = Qt.__binding__ == 'PySide' +Qt.IsPyQt4 = Qt.__binding__ == 'PyQt4' + +"""Augment QtCompat + +QtCompat contains wrappers and added functionality +to the original bindings, such as the CLI interface +and otherwise incompatible members between bindings, +such as `QHeaderView.setSectionResizeMode`. + +""" + +Qt.QtCompat._cli = _cli +Qt.QtCompat._convert = _convert + +# Enable command-line interface +if __name__ == "__main__": + _cli(sys.argv[1:]) + + +# The MIT License (MIT) +# +# Copyright (c) 2016-2017 Marcus Ottosson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# In PySide(2), loadUi does not exist, so we implement it +# +# `_UiLoader` is adapted from the qtpy project, which was further influenced +# by qt-helpers which was released under a 3-clause BSD license which in turn +# is based on a solution at: +# +# - https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 +# +# The License for this code is as follows: +# +# qt-helpers - a common front-end to various Qt modules +# +# Copyright (c) 2015, Chris Beaumont and Thomas Robitaille +# +# All rights reserved. +# +# 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 Glue project 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 HOLDER 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. +# +# Which itself was based on the solution at +# +# https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 +# +# which was released under the MIT license: +# +# Copyright (c) 2011 Sebastian Wiesner +# Modifications by Charl Botha +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files +# (the "Software"),to deal in the Software without restriction, +# including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/python/mmSolver/ui/base_maya_window.py b/python/mmSolver/ui/base_maya_window.py index 68bbae31d..163f01769 100644 --- a/python/mmSolver/ui/base_maya_window.py +++ b/python/mmSolver/ui/base_maya_window.py @@ -50,9 +50,9 @@ def apply(self): import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger import mmSolver.utils.config as config_utils diff --git a/python/mmSolver/ui/commonmenus.py b/python/mmSolver/ui/commonmenus.py index 7969085d9..2aa495cef 100644 --- a/python/mmSolver/ui/commonmenus.py +++ b/python/mmSolver/ui/commonmenus.py @@ -22,10 +22,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt as Qt -import Qt.QtGui as QtGui -import Qt.QtCore as QtCore -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.logger diff --git a/python/mmSolver/ui/converttypes.py b/python/mmSolver/ui/converttypes.py index c3e7649fb..4a95e8ac8 100644 --- a/python/mmSolver/ui/converttypes.py +++ b/python/mmSolver/ui/converttypes.py @@ -25,7 +25,7 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtCore as QtCore import mmSolver.logger import mmSolver.utils.converttypes as utils_convert diff --git a/python/mmSolver/ui/uimodels.py b/python/mmSolver/ui/uimodels.py index e20cd3dda..9f88a2eae 100644 --- a/python/mmSolver/ui/uimodels.py +++ b/python/mmSolver/ui/uimodels.py @@ -22,10 +22,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt as Qt -import Qt.QtGui as QtGui -import Qt.QtCore as QtCore -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtWidgets as QtWidgets import mmSolver.ui.converttypes as converttypes import mmSolver.ui.nodes as uinodes diff --git a/python/mmSolver/ui/uiutils.py b/python/mmSolver/ui/uiutils.py index 0be26f906..3ac2d7225 100644 --- a/python/mmSolver/ui/uiutils.py +++ b/python/mmSolver/ui/uiutils.py @@ -24,10 +24,10 @@ import mmSolver.ui.qtpyutils as qtpyutils qtpyutils.override_binding_order() -import Qt -import Qt.QtCore as QtCore -import Qt.QtGui as QtGui -import Qt.QtWidgets as QtWidgets +import mmSolver.ui.Qt as Qt +import mmSolver.ui.Qt.QtCore as QtCore +import mmSolver.ui.Qt.QtGui as QtGui +import mmSolver.ui.Qt.QtWidgets as QtWidgets def getHostApplication():