From 73287fcdcb8dc88f85b18040a156de23c161930b Mon Sep 17 00:00:00 2001 From: Ryan Griffin Date: Sat, 8 Jul 2017 19:41:20 -0400 Subject: [PATCH 1/4] reset --- .idea/Python_101_S2_2015.iml | 11 + .idea/misc.xml | 14 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 753 +++++++++++++++++ data/rig/arm.json | 1 - layout/.mayaSwatches/layout_chain.ma.swatches | Bin 0 -> 98431 bytes layout/layout_chain.ma | 758 ++++++++++++++++++ rig/rig_arm.py | 108 --- system/utils.py | 83 -- ui/__init__.pyc | Bin 153 -> 0 bytes ui/ui.py | 95 --- 12 files changed, 1550 insertions(+), 287 deletions(-) create mode 100644 .idea/Python_101_S2_2015.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml delete mode 100644 data/rig/arm.json create mode 100644 layout/.mayaSwatches/layout_chain.ma.swatches create mode 100644 layout/layout_chain.ma delete mode 100644 rig/rig_arm.py delete mode 100644 system/utils.py delete mode 100644 ui/__init__.pyc delete mode 100644 ui/ui.py diff --git a/.idea/Python_101_S2_2015.iml b/.idea/Python_101_S2_2015.iml new file mode 100644 index 0000000..6711606 --- /dev/null +++ b/.idea/Python_101_S2_2015.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..20a28a7 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8a69338 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..e8f1941 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,753 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1488570271749 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/rig/arm.json b/data/rig/arm.json deleted file mode 100644 index f41aa20..0000000 --- a/data/rig/arm.json +++ /dev/null @@ -1 +0,0 @@ -{"fkcontrols": ["ctrl_s_fk_shoulder", "ctrl_s_fk_elbow", "ctrl_s_fk_wrist"], "ikjnts": ["ik_s_shoulder_jnt", "ik_s_elbow_jnt", "ik_s_wrist_jnt", "ik_s_wristEnd_jnt"], "fkjnts": ["fk_s_shoulder_jnt", "fk_s_elbow_jnt", "fk_s_wrist_jnt", "fk_s_wristEnd_jnt"], "rigjnts": ["rig_s_shoulder_jnt", "rig_s_elbow_jnt", "rig_s_wrist_jnt", "rig_s_wristEnd_jnt"], "bindjnts": ["bind_s_shoulder_jnt", "bind_s_elbow_jnt", "bind_s_wrist_jnt", "bind_s_wristEnd_jnt"], "positions": [[0.0, 0.0, 0.0], [-1.0, 0.0, 2.0], [0.0, 0.0, 4.0], [0.0, 0.0, 6.0]], "ikcontrols": ["ctrl_s_ik_arm", "ikh_s_arm", "ctrl_s_pv_arm"]} \ No newline at end of file diff --git a/layout/.mayaSwatches/layout_chain.ma.swatches b/layout/.mayaSwatches/layout_chain.ma.swatches new file mode 100644 index 0000000000000000000000000000000000000000..133726f67201a34b7f2756ca03db0996f607db10 GIT binary patch literal 98431 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 Date: Mon, 24 Jul 2017 23:20:50 -0400 Subject: [PATCH 2/4] Add modules folder --- modules/PY101.mod | 4 ++++ startup.py | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 modules/PY101.mod diff --git a/modules/PY101.mod b/modules/PY101.mod new file mode 100644 index 0000000..912a8c8 --- /dev/null +++ b/modules/PY101.mod @@ -0,0 +1,4 @@ ++ Rigging_Tool 1.0 C:\Users\Griffy\Documents\GitHub\Python_101 +RIGGING_TOOL=C:\Users\Griffy\Documents\GitHub\Python_101 +DATA_PATH=C:\Users\Griffy\Documents\GitHub\Python_101\data +scripts: C:\Users\Griffy\Documents\GitHub\Python_101 \ No newline at end of file diff --git a/startup.py b/startup.py index a8d03f6..241a2cb 100644 --- a/startup.py +++ b/startup.py @@ -12,9 +12,6 @@ # Change the current linear unit to inches cmds.currentUnit( linear='cm' ) -# Set a system path to files. We can do this with the os module -os.environ["RDOJO_DATA"] = os.environ['RIGGING_TOOL'] + '/data' - import ui.ui as ui reload(ui) ui.RDojo_UI() \ No newline at end of file From 45adffd11c20dd4980dc80a4b998e6b48ec31d82 Mon Sep 17 00:00:00 2001 From: Ryan Griffin Date: Mon, 24 Jul 2017 23:52:26 -0400 Subject: [PATCH 3/4] utils --- system/utils.py | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 system/utils.py diff --git a/system/utils.py b/system/utils.py new file mode 100644 index 0000000..55a6c2a --- /dev/null +++ b/system/utils.py @@ -0,0 +1,103 @@ +import maya.cmds as cmds +from pymel.core import * +import json +import tempfile + +def writeJson(fileName, data): + with open(fileName, 'w') as outfile: + json.dump(data, outfile) + file.close(outfile) + +def readJson(fileName): + with open(fileName, 'r') as infile: + data = (open(infile.name, 'r').read()) + return data + + +def createJoint(name, position, instance): + # Use a list comprehension to build joints. + jnt_list = [cmds.joint(n=name[i].replace('_s_', instance), p=position[i]) for i in range(len(name))] + cmds.select(d=True) + return(jnt_list) + + +def createControl(ctrlinfo): + control_info = [] + for info in ctrlinfo: + # Create ik control + # Get ws position of wrist joint + pos = info[0] + # Create an empty group + ctrlgrp = cmds.group( em=True, name='grp_' + info[1] ) + # Create circle control object + ctrl = cmds.circle( n=info[1], nr=(0, 0, 1), c=(0, 0, 0) ) + # Parent the control to the group + cmds.parent(ctrl, ctrlgrp) + # Move the group to the joint + cmds.xform(ctrlgrp, t=pos, ws=True) + control_info.append([ctrlgrp, ctrl[0]]) + return(control_info) + + +def calculatePVPosition(jnts): + from maya import cmds , OpenMaya + start = cmds.xform(jnts[0] ,q=True ,ws=True, t=True) + mid = cmds.xform(jnts[1] ,q=True ,ws=True, t=True) + end = cmds.xform(jnts[2] ,q=True ,ws=True, t=True) + startV = OpenMaya.MVector(start[0] ,start[1],start[2]) + midV = OpenMaya.MVector(mid[0] ,mid[1],mid[2]) + endV = OpenMaya.MVector(end[0] ,end[1],end[2]) + startEnd = endV - startV + startMid = midV - startV + dotP = startMid * startEnd + proj = float(dotP) / float(startEnd.length()) + startEndN = startEnd.normal() + projV = startEndN * proj + arrowV = startMid - projV + arrowV*= 0.5 + finalV = arrowV + midV + return ([finalV.x , finalV.y ,finalV.z]) + +def connectThroughBC(parentsA, parentsB, children, instance, switchattr ): + constraints = [] + for j in range(len(children)): + switchPrefix = children[j].partition('_')[2] + bcNodeT = cmds.shadingNode("blendColors", asUtility=True, n='bcNodeT_switch_' + switchPrefix) + cmds.connectAttr(switchattr, bcNodeT + '.blender') + bcNodeR = cmds.shadingNode("blendColors", asUtility=True, n='bcNodeR_switch_' + switchPrefix) + cmds.connectAttr(switchattr, bcNodeR + '.blender') + bcNodeS = cmds.shadingNode("blendColors", asUtility=True, n='bcNodeS_switch_' + switchPrefix) + cmds.connectAttr(switchattr, bcNodeS + '.blender') + constraints.append([bcNodeT, bcNodeR, bcNodeS]) + # Input Parents + cmds.connectAttr(parentsA[j] + '.translate', bcNodeT + '.color1') + cmds.connectAttr(parentsA[j] + '.rotate', bcNodeR + '.color1') + cmds.connectAttr(parentsA[j] + '.scale', bcNodeS + '.color1') + if parentsB != 'None': + cmds.connectAttr(parentsB[j] + '.translate', bcNodeT + '.color2') + cmds.connectAttr(parentsB[j] + '.rotate', bcNodeR + '.color2') + cmds.connectAttr(parentsB[j] + '.scale', bcNodeS + '.color2') + # Output to Children + cmds.connectAttr(bcNodeT + '.output', children[j] + '.translate') + cmds.connectAttr(bcNodeR + '.output', children[j] + '.rotate') + cmds.connectAttr(bcNodeS + '.output', children[j] + '.scale') + return constraints + + +def findHighestTrailingNumber(names, basename): + import re + highestValue = 0 + + for n in names: + if objExists(n) == True: + n = str(n) + if n.find(basename) >= 0: + suffix = n.partition(basename)[2][0] + + if re.match("^[0-9]*$", suffix): + numericalElement = int(suffix) + + if numericalElement >= highestValue: + highestValue = numericalElement + 1 + else: + highestValue = 1 \ No newline at end of file From 9432a249e087d33975a2711813b7e25ec7459827 Mon Sep 17 00:00:00 2001 From: Ryan Griffin Date: Wed, 9 Aug 2017 22:44:36 -0400 Subject: [PATCH 4/4] PYSIDE UI EXAMPLES --- .idea/misc.xml | 10 - .idea/workspace.xml | 499 ++++++++----------- ui/MayaDockingClass.py | 150 ++++++ ui/Qt.py | 1030 ++++++++++++++++++++++++++++++++++++++++ ui/shiboken2.py | 36 ++ 5 files changed, 1408 insertions(+), 317 deletions(-) create mode 100644 ui/MayaDockingClass.py create mode 100644 ui/Qt.py create mode 100644 ui/shiboken2.py diff --git a/.idea/misc.xml b/.idea/misc.xml index 20a28a7..8fb2248 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,14 +1,4 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e8f1941..eb5381f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,10 +1,7 @@ - - - - + - - + + - - - - - + + + - - + + - + - - + + - - - - - + + + - - + + - - - - - + + + - - + + - - - - - + + + - - + + - - + + - + - + - - - + + + + + @@ -116,24 +107,16 @@ - - - - - - - - - - + @@ -150,32 +133,27 @@ + - - - - - - - - @@ -185,11 +163,11 @@ - - @@ -199,29 +177,11 @@ - - - - - - - - - - - - @@ -231,17 +191,29 @@ - - + + + + + @@ -272,7 +245,7 @@ - + - + - + - + - + @@ -392,26 +345,27 @@ - + - + + + + - - @@ -432,319 +386,250 @@ - + + + - - - - - + + + - + - - + + - + + + + - - + + - + - + + + + + - - - - - + + + - + + - - - - - + + + - + - - - - - + + + + + - - + + + + - - - - + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + - - - - + + - - - - + + - + + + - - - - + + - + - - - - - + + + - + + + + + + + - - + + - + - - - - - + + + - + - - + + - + - - + - + + - + - - - - - - - - - - - + + - + - - - - - + + + - + - - - - - + + + - + - + - + - - - - - - - - - - - - + + diff --git a/ui/MayaDockingClass.py b/ui/MayaDockingClass.py new file mode 100644 index 0000000..9d64f10 --- /dev/null +++ b/ui/MayaDockingClass.py @@ -0,0 +1,150 @@ +""" +This is what you need to do in order to get a qt window to dock next to maya channel box, +In all maya versions, including 2017 with PySide2 +""" +__author__ = "liorbenhorin@gmail.com" +__author__ = "rgriffin" + +import os +import logging + +# Qt is a project by Marcus Ottosson ---> https://github.com/mottosso/Qt.py +from Qt import QtGui, QtWidgets, QtCore, QtCompat + +try: + import pysideuic + from shiboken import wrapInstance + + logging.Logger.manager.loggerDict["pysideuic.uiparser"].setLevel(logging.CRITICAL) + logging.Logger.manager.loggerDict["pysideuic.properties"].setLevel(logging.CRITICAL) +except ImportError: + import pyside2uic as pysideuic + from shiboken2 import wrapInstance + + logging.Logger.manager.loggerDict["pyside2uic.uiparser"].setLevel(logging.CRITICAL) + logging.Logger.manager.loggerDict["pyside2uic.properties"].setLevel(logging.CRITICAL) + +import maya.OpenMayaUI as omui +from maya.app.general.mayaMixin import MayaQWidgetDockableMixin +import maya.cmds as cmds + + + +def maya_main_window(): + main_window_ptr = omui.MQtUtil.mainWindow() + return wrapInstance(long(main_window_ptr), QtWidgets.QWidget) + +def maya_api_version(): + return int(cmds.about(api=True)) + +class MyDockingWindow(MayaQWidgetDockableMixin, QtWidgets.QMainWindow): + MAYA2014 = 201400 + MAYA2015 = 201500 + MAYA2016 = 201600 + MAYA2016_5 = 201650 + MAYA2017 = 201700 + + def __init__(self, parent=None): + self.toolName = 'Dockable Window' + + self.deleteInstances() # remove any instance of this window before starting + + super(MyDockingWindow, self).__init__(parent) + + self.setWindowFlags(QtCore.Qt.Tool) + + self.setAttribute(QtCore.Qt.WA_DeleteOnClose) + + def dockCloseEventTriggered(self): + self.deleteInstances() + + # Delete any instances of this class + def deleteInstances(self): + + def delete2016(): + # Go through main window's children to find any previous instances + for obj in maya_main_window().children(): + + if str(type( + obj)) == "": # """: + + if obj.widget().__class__.__name__ == self.toolName: # Compare object names + + obj.setParent(None) + obj.deleteLater() + + def delete2017(): + ''' + Look like on 2017 this needs to be a little different, like in this function, + However, i might be missing something since ive done this very late at night :) + ''' + + for obj in maya_main_window().children(): + + if str(type(obj)) == "".format(os.path.splitext( + os.path.basename(__file__)[0])): # """: + + if obj.__class__.__name__ == "MyDockingWindow": # Compare object names + + obj.setParent(None) + obj.deleteLater() + + if maya_api_version() < MyDockingWindow.MAYA2017: + delete2016() + else: + delete2017() + + def deleteControl(self, control): + + if cmds.workspaceControl(control, q=True, exists=True): + cmds.workspaceControl(control, e=True, close=True) + cmds.deleteUI(control, control=True) + + # Show window with docking ability + def run(self): + ''' + 2017 docking is a little different... + ''' + + def run2017(): + self.setObjectName(self.toolName) + + # The deleteInstances() dose not remove the workspace control, and we need to remove it manually + workspaceControlName = self.objectName() + 'WorkspaceControl' + self.deleteControl(workspaceControlName) + + # this class is inheriting MayaQWidgetDockableMixin.show(), which will eventually call maya.cmds.workspaceControl. + # I'm calling it again, since the MayaQWidgetDockableMixin dose not have the option to use the "tabToControl" flag, + # which was the only way i found i can dock my window next to the channel controls, attributes editor and modelling toolkit. + self.show(dockable=True, floating=True) + #cmds.workspaceControl(workspaceControlName, e=True, ttc=["AttributeEditor", -1], wp="preferred", mw=420) + cmds.workspaceControl(workspaceControlName, e=True, wp="preferred") + self.raise_() + + # size can be adjusted, of course + self.setDockableParameters(width=420) + + def run2016(): + self.setObjectName(self.toolName) + # on maya < 2017, the MayaQWidgetDockableMixin.show() magiclly docks the window next + # to the channel controls, attributes editor and modelling toolkit. + self.show(dockable=True, floating=True) + self.raise_() + # size can be adjusted, of course + self.setDockableParameters(width=420) + self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + + if maya_api_version() < MyDockingWindow.MAYA2017: + run2016() + else: + run2017() + + +def show(): + ''' + this is the function that start things up + ''' + global MyDockingWindow + MyDockingWindow = MyDockingWindow(parent=maya_main_window()) + MyDockingWindow.run() + return MyDockingWindow diff --git a/ui/Qt.py b/ui/Qt.py new file mode 100644 index 0000000..3a97da8 --- /dev/null +++ b/ui/Qt.py @@ -0,0 +1,1030 @@ +"""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. + +Documentation + + Map all bindings to PySide2 + + Project goals: + 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 + +""" + +import os +import sys +import types +import shutil +import importlib + +__version__ = "1.0.0.b3" + +# 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") + +"""Common members of all bindings + +This is where each member of Qt.py is explicitly defined. +It is based on a "lowest commond denominator" of all bindings; +including members found in each of the 4 bindings. + +Find or add excluded members in build_membership.py + +""" + +_common_members = { + "QtGui": [ + "QAbstractTextDocumentLayout", + "QActionEvent", + "QBitmap", + "QBrush", + "QClipboard", + "QCloseEvent", + "QColor", + "QConicalGradient", + "QContextMenuEvent", + "QCursor", + "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", + "QTransform", + "QValidator", + "QVector2D", + "QVector3D", + "QVector4D", + "QWhatsThisClickedEvent", + "QWheelEvent", + "QWindowStateChangeEvent", + "qAlpha", + "qBlue", + "qGray", + "qGreen", + "qIsGray", + "qRed", + "qRgb", + "qRgb", + ], + "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", + ], + "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", + "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", + "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", + ], + "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" + ], + "QtHelp": [ + "QHelpContentItem", + "QHelpContentModel", + "QHelpContentWidget", + "QHelpEngine", + "QHelpEngineCore", + "QHelpIndexModel", + "QHelpIndexWidget", + "QHelpSearchEngine", + "QHelpSearchQuery", + "QHelpSearchQueryWidget", + "QHelpSearchResultWidget" + ], + "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" + ] +} + + +def _new_module(name): + return types.ModuleType(__name__ + "." + name) + + +def _setup(module, extras): + """Install common submodules""" + + Qt.__binding__ = module.__name__ + + for name in list(_common_members) + extras: + try: + # print("Trying %s" % name) + submodule = importlib.import_module( + module.__name__ + "." + name) + except ImportError: + # print("Failed %s" % name) + 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 _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 + _setup(module, ["QtUiTools"]) + + Qt.__binding_version__ = module.__version__ + + if hasattr(Qt, "_QtUiTools"): + Qt.QtCompat.loadUi = lambda fname: \ + Qt._QtUiTools.QUiLoader().load(fname) + + if hasattr(Qt, "_QtGui") and hasattr(Qt, "_QtCore"): + Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel + + if hasattr(Qt, "_QtWidgets"): + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtWidgets.QHeaderView.setSectionResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.__qt_version__ = Qt._QtCore.qVersion() + Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate + + Qt.QtCore.Property = Qt._QtCore.Property + Qt.QtCore.Signal = Qt._QtCore.Signal + Qt.QtCore.Slot = Qt._QtCore.Slot + + Qt.QtCore.QAbstractProxyModel = Qt._QtCore.QAbstractProxyModel + Qt.QtCore.QSortFilterProxyModel = Qt._QtCore.QSortFilterProxyModel + Qt.QtCore.QItemSelection = Qt._QtCore.QItemSelection + Qt.QtCore.QItemSelectionRange = Qt._QtCore.QItemSelectionRange + Qt.QtCore.QItemSelectionModel = Qt._QtCore.QItemSelectionModel + + +def _pyside(): + """Initialise PySide""" + + import PySide as module + _setup(module, ["QtUiTools"]) + + Qt.__binding_version__ = module.__version__ + + if hasattr(Qt, "_QtUiTools"): + Qt.QtCompat.loadUi = lambda fname: \ + Qt._QtUiTools.QUiLoader().load(fname) + + if hasattr(Qt, "_QtGui"): + setattr(Qt, "QtWidgets", _new_module("QtWidgets")) + setattr(Qt, "_QtWidgets", Qt._QtGui) + + Qt.QtCompat.setSectionResizeMode = Qt._QtGui.QHeaderView.setResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.QtCore.QAbstractProxyModel = Qt._QtGui.QAbstractProxyModel + Qt.QtCore.QSortFilterProxyModel = Qt._QtGui.QSortFilterProxyModel + Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel + Qt.QtCore.QItemSelection = Qt._QtGui.QItemSelection + Qt.QtCore.QItemSelectionRange = Qt._QtGui.QItemSelectionRange + Qt.QtCore.QItemSelectionModel = Qt._QtGui.QItemSelectionModel + + if hasattr(Qt, "_QtCore"): + Qt.__qt_version__ = Qt._QtCore.qVersion() + + Qt.QtCore.Property = Qt._QtCore.Property + Qt.QtCore.Signal = Qt._QtCore.Signal + Qt.QtCore.Slot = Qt._QtCore.Slot + + QCoreApplication = Qt._QtCore.QCoreApplication + Qt.QtCompat.translate = ( + lambda context, sourceText, disambiguation, n: + QCoreApplication.translate( + context, + sourceText, + disambiguation, + QCoreApplication.CodecForTr, + n + ) + ) + + +def _pyqt5(): + """Initialise PyQt5""" + + import PyQt5 as module + _setup(module, ["uic"]) + + if hasattr(Qt, "_uic"): + Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname) + + if hasattr(Qt, "_QtWidgets"): + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtWidgets.QHeaderView.setSectionResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate + + Qt.QtCore.Property = Qt._QtCore.pyqtProperty + Qt.QtCore.Signal = Qt._QtCore.pyqtSignal + Qt.QtCore.Slot = Qt._QtCore.pyqtSlot + + Qt.QtCore.QAbstractProxyModel = Qt._QtCore.QAbstractProxyModel + Qt.QtCore.QSortFilterProxyModel = Qt._QtCore.QSortFilterProxyModel + Qt.QtCore.QStringListModel = Qt._QtCore.QStringListModel + Qt.QtCore.QItemSelection = Qt._QtCore.QItemSelection + Qt.QtCore.QItemSelectionModel = Qt._QtCore.QItemSelectionModel + Qt.QtCore.QItemSelectionRange = Qt._QtCore.QItemSelectionRange + + Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR + Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR + + +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 + _setup(module, ["uic"]) + + if hasattr(Qt, "_uic"): + Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname) + + if hasattr(Qt, "_QtGui"): + setattr(Qt, "QtWidgets", _new_module("QtWidgets")) + setattr(Qt, "_QtWidgets", Qt._QtGui) + + Qt.QtCompat.setSectionResizeMode = \ + Qt._QtGui.QHeaderView.setResizeMode + + if hasattr(Qt, "_QtCore"): + Qt.QtCore.QAbstractProxyModel = Qt._QtGui.QAbstractProxyModel + Qt.QtCore.QSortFilterProxyModel = Qt._QtGui.QSortFilterProxyModel + Qt.QtCore.QItemSelection = Qt._QtGui.QItemSelection + Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel + Qt.QtCore.QItemSelectionModel = Qt._QtGui.QItemSelectionModel + Qt.QtCore.QItemSelectionRange = Qt._QtGui.QItemSelectionRange + + if hasattr(Qt, "_QtCore"): + Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR + Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR + + Qt.QtCore.Property = Qt._QtCore.pyqtProperty + Qt.QtCore.Signal = Qt._QtCore.pyqtSignal + Qt.QtCore.Slot = Qt._QtCore.pyqtSlot + + QCoreApplication = Qt._QtCore.QCoreApplication + Qt.QtCompat.translate = ( + lambda context, sourceText, disambiguation, n: + QCoreApplication.translate( + context, + sourceText, + disambiguation, + QCoreApplication.CodecForTr, + n) + ) + + +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 fname: 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") + line = line.replace("QtWidgets.QApplication.translate", + "Qt.QtCompat.translate") + 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)) + + 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) + + # Backwards compatibility + Qt.QtCompat.load_ui = Qt.QtCompat.loadUi + + +_install() + + +"""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:]) diff --git a/ui/shiboken2.py b/ui/shiboken2.py new file mode 100644 index 0000000..8e7b6da --- /dev/null +++ b/ui/shiboken2.py @@ -0,0 +1,36 @@ +def isValid(*args, **kwargs): + pass + + +def invalidate(*args, **kwargs): + pass + + +def dump(*args, **kwargs): + pass + + +def createdByPython(*args, **kwargs): + pass + + +def delete(*args, **kwargs): + pass + + +def wrapInstance(*args, **kwargs): + pass + + +def getCppPointer(*args, **kwargs): + pass + + +def ownedByPython(*args, **kwargs): + pass + + + +__version__ = '2.0.0' + +