Changelogs » Qt.py

Qt.py

1.2.3

New mechanism for warning about members that are missing and supposed to be missing, currently only `QtGui.QMatrix`.

If you discover or know about a member that isn't in Qt.py and shouldn't be, you can add a it to [`_missing_members`](https://github.com/mottosso/Qt.py/blob/62dc86b3a610133b959f5af037f31c3728992faa/Qt.pyL692).

py
_missing_members = {
"QtGui": {
"QMatrix": "Deprecated in PyQt5",
"YOUR MEMBER": "Message to display whenever anyone tries to access it"
},
}

1.2.2

- Added `QtCompat.QStyleOptionViewItemV4`

python
>>> from Qt import QtCompat
>>> QtCompat.QStyleOptionViewItemV4
<class 'PyQt5.QtWidgets.QStyleOptionViewItem'>


See https://github.com/mottosso/Qt.py/pull/329 for details.

1.2.1

Cosmetic change only.

Support for Rez's version resolution algorithm, which puts pre-releases ahead of stable releases.

- See nerdvegas/rez653

1.2.0

Added:

- `QtCompat.dataChanged`
- `QtCompat.isValid`

Merged:

- 306
- 285

1.2.0.b3

Workaround to [pyside-77](https://bugreports.qt.io/browse/PYSIDE-77) bug.

See https://github.com/mottosso/Qt.py/pull/306 for details. Thanks to aoblet for this fix!

1.2.0.b2

Internal changes to facilitate the [QtPyConvert project](https://github.com/digitaldomain/QtPyConvert), should not affect the end-user.

- [Details](https://github.com/mottosso/Qt.py/pull/285)

1.1.0

Improved detection of common members

The ability to automatically _generate_ the common members, used by Qt.py, makes it much easier to spot new additions to e.g. PySide2. Run `build_membership.sh` to generate a JSON file per binding, which are then compared. The result is written to a `common_members.json` and can be copy-pasted into Qt.py. This comparison leverages the tests suite and uses the binding versions used in the latest test suite.

Once the binding versions used by the tests suite gets updated (usually annually during a VFX Platform update), we will check for new members, using this new approach.

See [DOCKER.md](DOCKER.md) for more info.

<br>

New members


QtCore.QItemSelectionRange   thanks to Ahuge
QtCore.QT_TRANSLATE_NOOP
QtCore.QT_TR_NOOP
QtCore.QT_TR_NOOP_UTF8

QtGui.DesktopServices
QtGui.QTouchEvent
QtGui.qRgba

QtMultimedia.QAbstractVideoBuffer
QtMultimedia.QAbstractVideoSurface
QtMultimedia.QAudio
QtMultimedia.QAudioDeviceInfo
QtMultimedia.QAudioFormat
QtMultimedia.QAudioInput
QtMultimedia.QAudioOutput
QtMultimedia.QVideoFrame
QtMultimedia.QVideoSurfaceFormat

QtPrintSupport.QAbstractPrintDialog
QtPrintSupport.QPageSetupDialog
QtPrintSupport.QPrintDialog
QtPrintSupport.QPrintEngine
QtPrintSupport.QPrintPreviewDialog
QtPrintSupport.QPrintPreviewWidget
QtPrintSupport.QPrinter
QtPrintSupport.QPrinterInfo

QtSql.QSql
QtSql.QSqlDatabase
QtSql.QSqlDriver
QtSql.QSqlDriverCreatorBase
QtSql.QSqlError
QtSql.QSqlField
QtSql.QSqlIndex
QtSql.QSqlQuery
QtSql.QSqlQueryModel
QtSql.QSqlRecord
QtSql.QSqlRelation
QtSql.QSqlRelationalDelegate
QtSql.QSqlRelationalTableModel
QtSql.QSqlResult
QtSql.QSqlTableModelQtSql

QtSvg.QGraphicsSvgItem
QtSvg.QSvgGenerator
QtSvg.QSvgRenderer
QtSvg.QSvgWidget

QTest.QTest

QtX11Extras.QX11Info   thanks to assumptionsoup

QtXmlPatterns.QAbstractMessageHandler
QtXmlPatterns.QAbstractUriResolver
QtXmlPatterns.QAbstractXmlNodeModel
QtXmlPatterns.QAbstractXmlReceiver
QtXmlPatterns.QSourceLocation
QtXmlPatterns.QXmlFormatter
QtXmlPatterns.QXmlItem
QtXmlPatterns.QXmlName
QtXmlPatterns.QXmlNamePool
QtXmlPatterns.QXmlNodeModelIndex
QtXmlPatterns.QXmlQuery
QtXmlPatterns.QXmlResultItems
QtXmlPatterns.QXmlSchema
QtXmlPatterns.QXmlSchemaValidator
QtXmlPatterns.QXmlSerializer"


<br>

Removed QtCore.QMetaType member

The `QtCore.QMetaType` member was removed as it was wrongly added to Qt.py.

<br>

New tests suite

A new tests suite was added. Qt and its bindings are compiled from source using the CY2018 VFX Platform standards. This adds better support for testing with Python 3.x and removes the dependency of the Ubuntu PPAs previously used to install the Qt bindings.

bash
cd Qt.py

Run nosetests (Linux/OSX)
docker run --rm -v $(pwd):/Qt.py -e PYTHON=2.7 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.4 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.5 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.6 fredrikaverpil/qt.py:2018

Run nosetests (Windows)
docker run --rm -v %CD%:/Qt.py -e PYTHON=2.7 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.4 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.5 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.6 fredrikaverpil/qt.py:2018


The test suite will be updated anually, around the time of SIGGRAPH and when the VFX Platform usually gets updated.

For more information on running the tests, see [README.md](README.md) and [DOCKER.md](DOCKER.md).

<br>

Support for Python 2.6

Qt.py now works with Python 2.6, thanks to contributions made by Ahuge (see 245). However, keep in mind that the automatic tests don't apply to Python 2.6.

<br>

Upgraded QtCompat

An additional layer was added to `QtCompat` to facilitate more members.

**Before**

python
from Qt import QtCompat
QtCompat.setSectionResizeMode


**After**

python
from Qt import QtCompat
QtCompat.QHeaderView.setSectionResizeMode


**Backwards compatibility is maintained**, at least till the next major version release.

<br>



Pre-release installation

**Install**

To install a pre-release, prepend `--pre` to your `pip install`.

bash
$ pip install --pre -U Qt.py


To upgrade an existing install, prepend `-U` as well.


bash
$ pip install --pre Qt.py



<br>


`QtSiteConfig`

Version 1.1.0.b3 added support for overriding available members of Qt.py on import, to either add custom members and modules, or remove them.

- [Documentation](https://github.com/mottosso/Qt.pyqtsiteconfigpy)

<br>


Added `wrapInstance` and `getCppPointer`

The `shiboken` of PySide and `sip` of PyQt have found a home in `QtCompat`.

python
from Qt import QtCompat
QtCompat.wrapInstance(...)


They work similar as you would expect. See [the release notes for 1.1.0.b1](https://github.com/mottosso/Qt.py/releases/tag/1.1.0.b1) for details and examples.

1.1.0.b10

Adds support for `from Qt.QtCompat import X`.

See https://github.com/mottosso/Qt.py/pull/265 for details.

1.1.0.b9

Improvements to `QtCompat.loadUi()`.

- See https://github.com/mottosso/Qt.py/pull/217 for details.

1.1.0.b8

Here are the changes coming from 234:

A new tests suite was added. Qt and its bindings are compiled from source using the CY2018 VFX Platform standards. This adds better support for testing with Python 3.x and removes the dependency of the Ubuntu PPAs previously used to install the Qt bindings.

* The common members dictionary is now based on a proper comparison. As a result, [new members](https://github.com/mottosso/Qt.py/pull/234/filesdiff-cd1d7c0a982bce680146d5b248151256) were found to be common. Run `build_membership.py` to generate JSON files which gets compared and in finally generates `common_bindings.json` which serves as a base for the `common_members` dictionary in Qt.py.
* `DOCKER.md` `README.md` were updated with instructions and details on testing.
* [`QtCompat.wrapInstance` caveats test](https://github.com/mottosso/Qt.py/pull/234/filesdiff-915339f1306346f3f70f708409018718) is skipped with PySide2 due to this having been addressed by QtC.

1.1.0.b7

Added support (where available) for QtX11Extras.

- See [PR](https://github.com/mottosso/Qt.py/pull/255)

Thanks to assumptionsoup for this feature!

1.1.0.b6

Re-added `QItemSelectionRange` to `QtCore`.

- See https://github.com/mottosso/Qt.py/pull/253

Thanks Ahuge!

1.1.0.b4

Support for Python 2.6.

- See 245

Thanks Ahuge!

1.1.0.b3

Upgraded QtCompat

An additional layer was added to `QtCompat` to facilitate more members.

**Before**

python
from Qt import QtCompat
QtCompat.setSectionResizeMode


**After**

python
from Qt import QtCompat
QtCompat.QHeaderView.setSectionResizeMode


**Backwards compatibility is maintained** till the next major version release.

<br>

`QtSiteConfig` example

> From [/examples](https://github.com/mottosso/Qt.py/tree/master/examples/QtSiteConfig)

This example illustrates how to make a QtSiteConfig module and how it affects Qt.py at run-time.

**Usage**

bash
$ cd to/this/directory
$ python main.py
Qt.QtCore was successfully removed by QSiteConfig.py


Because `QtSiteConfig.py` is in the current working directory, it is available to import by Python. If running from a different directory, then you can append this directory to your `PYTHONPATH`

bash
$ set PYTHONPATH=path/to/QtSiteConfig/
$ python main.py
Qt.QtCore was successfully removed by QSiteConfig.py


> Linux and MacOS users: Replace `set` with `export`

<br>

**Advanced examples**

If you need to you can also add modules that are not in the standard Qt.py. All of these functions are optional in QtSiteConfig, so only implement the functions you need.

QtSiteConfig.py: Adding non-standard modules

By default Qt.py only exposes the "lowest common denominator" of all bindings. This example shows how to add the Qsci module that is not included by default with Qt.py.

python
def update_members(members):
"""An example of adding Qsci to Qt.py.

Arguments:
members (dict): The default list of members in Qt.py.
Update this dict with any modifications needed.
"""

Include Qsci module for scintilla lexer support.
members["Qsci"] = [
"QsciAPIs",
"QsciAbstractAPIs",
"QsciCommand",
"QsciCommandSet",
"QsciDocument",
"QsciLexer",
"QsciLexerAVS",
"QsciLexerBash",
"QsciLexerBatch",
"QsciLexerCMake",
"QsciLexerCPP",
"QsciLexerCSS",
"QsciLexerCSharp",
"QsciLexerCoffeeScript",
"QsciLexerCustom",
"QsciLexerD",
"QsciLexerDiff",
"QsciLexerFortran",
"QsciLexerFortran77",
"QsciLexerHTML",
"QsciLexerIDL",
"QsciLexerJSON",
"QsciLexerJava",
"QsciLexerJavaScript",
"QsciLexerLua",
"QsciLexerMakefile",
"QsciLexerMarkdown",
"QsciLexerMatlab",
"QsciLexerOctave",
"QsciLexerPO",
"QsciLexerPOV",
"QsciLexerPascal",
"QsciLexerPerl",
"QsciLexerPostScript",
"QsciLexerProperties",
"QsciLexerPython",
"QsciLexerRuby",
"QsciLexerSQL",
"QsciLexerSpice",
"QsciLexerTCL",
"QsciLexerTeX",
"QsciLexerVHDL",
"QsciLexerVerilog",
"QsciLexerXML",
"QsciLexerYAML",
"QsciMacro",
"QsciPrinter",
"QsciScintilla",
"QsciScintillaBase",
"QsciStyle",
"QsciStyledText",
]



QtSiteConfig.py: Standardizing the location of Qt classes

Some classes have been moved to new locations between bindings. Qt.py uses the namespace dictated by PySide2 and most members are already in place.
This example reproduces functionality already in Qt.py but it provides a good example of how use this function.

python
def update_misplaced_members(members):
"""This optional function is called by Qt.py to standardize the location
and naming of exposed classes.

Arguments:
members (dict): The members considered by Qt.py
"""
Standardize the the Property name
members["PySide2"]["QtCore.Property"] = "QtCore.Property"
members["PyQt5"]["QtCore.pyqtProperty"] = "QtCore.Property"
members["PySide"]["QtCore.Property"] = "QtCore.Property"
members["PyQt4"]["QtCore.pyqtProperty"] = "QtCore.Property"


QtSiteConfig.py: Standardizing PyQt4's QFileDialog functionality

This example reproduces functionality already in Qt.py but it provides a good example of what is necessary to create your QtCompat namespaces with custom method decorators to change how the source method runs.

python
def update_compatibility_members(members):
"""This function is called by Qt.py to modify the modules it exposes.

Arguments:
members (dict): The members considered by Qt.py
"""
members['PyQt4']["QFileDialog"] = {
"getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName",
"getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames",
"getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName",
}

def update_compatibility_decorators(binding, decorators):
""" This function is called by Qt.py to modify the decorators applied to
QtCompat namespace objects. Defining this method is optional.

Arguments:
binding (str): The Qt binding being wrapped by Qt.py
decorators (dict): Maps specific decorator methods to
QtCompat namespace methods. See Qt._build_compatibility_members
for more info.
"""
if binding == '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, '')
preserve docstring and name of original method
wrapper.__doc__ = some_function.__doc__
wrapper.__name__ = some_function.__name__
return wrapper

decorators.setdefault("QFileDialog",{})["getOpenFileName"] = \
_standardizeQFileDialog
decorators.setdefault("QFileDialog",{})["getOpenFileNames"] = \
_standardizeQFileDialog
decorators.setdefault("QFileDialog",{})["getSaveFileName"] = \
_standardizeQFileDialog

1.1.0.b2

Maintenance release.

- Fix 213 and 222

**Install**

To install a pre-release, prepend `--pre` to your `pip install`.

bash
$ pip install --pre -U Qt.py


To upgrade an existing install, prepend `-U` as well.


bash
$ pip install --pre Qt.py

1.1.0.b1

This adds a wrapper for `wrapInstance` and `getCppPointer` from `shiboken2` and automatically unifies the differences with `shiboken` and `sip` for both Python 2 and 3.

| Attribute               | Returns
|:------------------------|:-----------
| `QtCompat.wrapInstance(addr=long, type=QObject)` | `QObject` |
`QtCompat.getCppPointer(object=QObject)`    | `long`

- See 53 for details.
- To **test**, copy/paste [this file](https://raw.githubusercontent.com/abstractfactory/Qt.py/implement59/Qt.py)

**Usage**

python
import sys
from Qt import QtCompat, QtWidgets
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("Hello world")
pointer = QtCompat.getCppPointer(button)
widget = QtCompat.wrapInstance(long(pointer), QtWidgets.QWidget)
assert widget == button
app.exit()


**Maya Example**

This works for both 2016 and 2017.

python
import sys
from maya import OpenMayaUI
from Qt import QtCompat, QtWidgets
pointer = OpenMayaUI.MQtUtil.mainWindow()
widget = QtCompat.wrapInstance(long(pointer), QtWidgets.QWidget)
assert isinstance(widget, QtWidgets.QWidget)


Important

This addition requires `sip`, `shiboken` or `shiboken2` to be available on your system. If not found, Qt.py will still import successfully, but these members will not be available.

In such cases, here is a Qt-only version and guaranteed cross-compatible version of the above.

python
from Qt import QtWidgets
app = QtWidgets.QApplication.instance()
widget = {o.objectName(): o for o in app.topLevelWidgets()}["MayaWindow"]


The same pattern may be applied to any and all uses of `sip`, `shiboken` and `shiboken2`, as discussed in-depth at 53.

Enjoy!

More Examples

For consideration into the main README.

`wrapInstance` have found particular use in Autodesk Maya, below are a few scenarios in which it is commonly used along with cross-binding alternatives.

<br>

Finding Widget Through MEL

**shiboken**

python
from maya import mel, OpenMayaUI
from Qt import QtWidgets
import shiboken2

status_line = mel.eval('$temp=$gStatusLineForm')
ptr = OpenMayaUI.MQtUtil.findControl(status_line)
status_line = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)
status_line = status_line.children()[1].children()[1]
status_line.setStyleSheet("QWidget {background: red}")


**Qt**

python
from maya import mel
from Qt import QtWidgets
app = QtWidgets.QApplication.instance()
window = {o.objectName(): o for o in app.topLevelWidgets()}["MayaWindow"]
status_line = mel.eval('$temp=$gStatusLineForm')
status_line = window.findChild(QtGui.QWidget, gStatusLine)
status_lne.setStyleSheet("QWidget {background: red}")


<br>

Finding Widget through Object Name

**shiboken**

python
import shiboken
import maya.OpenMayaUI as apiUI
from Qt import QtWidgets
channel_box = apiUI.MQtUtil.findControl("mainChannelBox")
channel_box = shiboken.wrapInstance(long(channel_box), QtWidgets.QTableView)
channel_box.setStyleSheet("QWidget {background: red}")


**Qt**

python
from Qt import QtWidgets
app = QtWidgets.QApplication.instance()
window = {o.objectName(): o for o in app.topLevelWidgets()}["MayaWindow"]
channel_box = window.findChild(QtWidgets.QTableView, "mainChannelBox")
channel_box.setStyleSheet("QWidget {background: green}")


<br>

Custom Attribute Editor Template

For testing purposes, we'll create a custom node and associate an attribute editor template with it. The modification of the resulting template via Qt is what differs between `shiboken` and `Qt`.

**Boilerplate**

These two files are identical and cross-compatible.

c
// AEMyNodeTemplate.mel

global proc AEMyNodeTemplate(string $nodeName)
{
editorTemplate -beginScrollLayout;
editorTemplate -beginLayout "My Attributes" -collapse 0;
editorTemplate -callCustom "MyNode_build_ui" "MyNode_update_ui" $nodeName;
editorTemplate -addControl "x";
editorTemplate -addControl "y";
editorTemplate -addControl "z";
editorTemplate -endLayout;
editorTemplate -addExtraControls;
editorTemplate -endScrollLayout;
}

global proc MyNode_build_ui( string $nodeName )
{
string $parent = `setParent -q`;
python("import myNodeUi");
python("myNodeUi.build_ui('" + $parent + "', '" + $nodeName + "')");
}

global proc MyNode_update_ui( string $nodeName )
{
string $parent = `setParent -q`;
python("myNodeUi.update_ui('" + $parent + "', '" + $nodeName + "')");
}


python
myNode.py
from maya import OpenMaya, OpenMayaMPx

kPluginNodeName = "MyNode"
MyNodeId = OpenMaya.MTypeId(524286)


class MyNode(OpenMayaMPx.MPxNode):
_x = OpenMaya.MObject()
_y = OpenMaya.MObject()
_z = OpenMaya.MObject()

def __init__(self):
OpenMayaMPx.MPxNode.__init__(self)

def compute(self, plug, data_block):
print("Computing..")


def MyNodeCreator():
return OpenMayaMPx.asMPxPtr(MyNode())


def MyNodeInit():
attr = OpenMaya.MFnNumericAttribute()
MyNode._x = attr.create("x", "x", OpenMaya.MFnNumericData.kFloat, 0.0)
attr.setKeyable(True)
MyNode._y = attr.create("y", "y", OpenMaya.MFnNumericData.kFloat, 0.0)
attr.setKeyable(True)
MyNode._z = attr.create("z", "z", OpenMaya.MFnNumericData.kFloat, 0.0)
attr.setKeyable(True)
MyNode.addAttribute(MyNode._x)
MyNode.addAttribute(MyNode._y)
MyNode.addAttribute(MyNode._z)


def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
mplugin.registerNode(
kPluginNodeName,
MyNodeId,
MyNodeCreator,
MyNodeInit,
OpenMayaMPx.MPxNode.kDependNode
)


def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
mplugin.deregisterNode(MyNodeId)


**shiboken**

Notice the OpenMayaUI and shiboken dependency.

python
myNodeUi.py
from maya import cmds, OpenMayaUI

from Qt import QtWidgets

if cmds.about(api=True) >= 201700:
from shiboken2 import wrapInstance
else:
from shiboken import wrapInstance

def build_ui(layout, node):
layout_ptr = OpenMayaUI.MQtUtil.findLayout(layout)
layout_obj = wrapInstance(long(layout_ptr), QtWidgets.QWidget)
layout_wid = layout_obj.findChild(QtWidgets.QBoxLayout)   Cast to QBoxLayout

widget = QtWidgets.QLabel("Hello World")
layout_wid.insertWidget(0, widget)

def update_ui(layout, node):
pass


**Qt**

python
myNodeUi.py
from Qt import QtWidgets

def build_ui(layout, node):
app = QtWidgets.QApplication.instance()
window = {o.objectName(): o for o in app.topLevelWidgets()}["MayaWindow"]

parent = window
for child in layout.split("|")[1:]:
parent = parent.findChild(QtWidgets.QWidget, child)

widget = QtWidgets.QLabel("Hello World")
layout = parent.findChild(QtWidgets.QBoxLayout)   Cast to QBoxLayout
layout.insertWidget(0, widget)

def update_ui(layout, node):
pass


Get top-level window in any binding and any application.

sip and shiboken is sometimes used to fetch the main window of an application in order to make it a parent of a custom window. Below is an example of how to find said window efficiently and in any situation.

python
from Qt import QtWidgets

current = QtWidgets.QApplication.activeWindow()
while current:
parent = current
current = parent.parent()

print(parent)


**Limitations**

- If run from within an already custom window that *did not* have it's parent set to the main window or a descendant of it, then this will return the custom window and may exit when it exists.

1.0

This **BACKWARDS INCOMPATIBLE** version boasts quite a few additions and changes.

- Enforce PySide2 API | Read more [here](https://github.com/mottosso/Qt.py/pull/173) and [here](https://github.com/mottosso/Qt.py/issues/152)
- Optional Submodules, now you can use Qt.py on distribution missing common members, such as in Houdini, along with QML, OpenGL and third-party additions like Qscintilla | [Read more](https://github.com/mottosso/Qt.py/pull/186)
- Improved consistency, `load_ui()` is now called `loadUi()`, just like its original | [Read more](https://github.com/mottosso/Qt.py/releases/tag/1.0.0.b3)
- Support for `baseinstance` in `loadUi()` | [Read more](https://github.com/mottosso/Qt.py/releases/tag/1.0.0.b4)
- Binding constants reap the benefits of static checking from your IDE | [Read more](https://github.com/mottosso/Qt.py/releases/tag/1.0.0.b5)

1.0.0


      

1.0.0.b6

QtSiteConfig.py

Individual members of Qt.py may now be customised via an additional module called `QtSiteConfig.py`. For example, one could remove `QtCore` if for whatever reason it shouldn't be used at all, or add site-specific modules like [`Qsci`](http://pyqt.sourceforge.net/Docs/QScintilla2/).

- [Documentation](https://github.com/mottosso/Qt.pyqtsiteconfigpy)
- [Original pull-request](https://github.com/mottosso/Qt.py/pull/207)

Thanks to MHendricks for this feature!

1.0.0.b5

Added support for binding constants.

python
import Qt

Before
if Qt.__binding__ == "PyQt5":
Do PyQt5 things

After
if Qt.IsPyQt5:
Do PyQt5 things


Which in addition to cutting down on typed characters also enables your IDE to detect potential misspellings. The previous method still exists and continues to work, there are no plans to deprecate it.

Thanks to dgovil for this feature!

1.0.0.b4

Added support for `baseinstance` to `QtCompat.loadUi()`.

python
QtCompat.loadUi(uifile="my.ui", baseinstance=QtWidgets.QWidget)


This feature mimics the functionality (warts and all) of `PyQt5.uic.loadUi` found [here](http://pyqt.sourceforge.net/Docs/PyQt5/designer.htmlPyQt5.uic.loadUi).

- [Documentation](https://github.com/mottosso/Qt.pyloading-qt-designer-files)
- See 196 for more details.

Thanks to dgovil for this feature!

1.0.0.b3

**Beta** release of 179.

python
Before
from Qt import QtCompat
QtCompat.load_ui(...)

After
from Qt import QtCompat
QtCompat.loadUi(...)


This is backwards compatible, `QtCompat.load_ui` will continue to be available but is to be considered deprecated.

See 177

1.0.0.b2

**Beta** release of 185.

- See 186 for details.

1.0.0b1

**Beta** release of 152, an enforced PySide2 API.

- See 173 for more details.

0.6.9

Maintenance release, it fixes the internal `QT_TESTING` environment variable such that members are properly tested during testing on Travis CI.

Thanks to sol-ansano-kim for the fix!

0.6.8

This release fixes 162 and makes the Qt.py wheel universal. This means no more wheel filename fragmentation.

Previous wheel filename fragmentation

Previously, `pip wheel -w . Qt.py` could generate one of the following:


Qt.py-0.6.7-py2-none-any.whl
Qt.py-0.6.7-py3-none-any.whl


or...


Qt.py-0.6.7-cp27-none-any.whl
Qt.py-0.6.7-cp35-none-any.whl
...


New wheel file naming

The wheels is now universal and `pip wheel -w . Qt.py` results in the following:


Qt.py-0.6.8-py2.py3-none-any.whl

0.6.8.dev2

This is a test release to attempt to produce a universal wheel.

0.6.8.dev1

This is a test release to attempt to produce a universal wheel.


0.6.8-test-01
This is a test release to attempt to produce a universal wheel.

0.6.7

This fixes 165 where `Qt.QtCompat.__binding_version__` and `Qt.QtCompat.__qt_version__` would both return `0.0.0` at all times.

0.6.6

This release fixes 160, where the Qt 4 version of `setSectionResizeMode` had broken since 0.6.1.

The fault was on me, having wrongly interpreted `setSectionResizeMode` as `setSectionHidden` in the [documentation](http://doc.qt.io/qt-4.8/qheaderview.htmlsetSectionHidden).

Surprisingly, the [CAVEATS test](https://github.com/mottosso/Qt.py/blob/master/CAVEATS.mdqtwidgetsqheaderviewsetresizemode) didn't catch it.