Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions Qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@
import sys
import types
import shutil
import importlib


__version__ = "1.2.0.b2"
__version__ = "1.2.0.b3"

# Enable support for `from Qt import *`
__all__ = []
Expand Down Expand Up @@ -851,6 +852,41 @@ class _UiLoader(Qt._QtUiTools.QUiLoader):
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
Expand All @@ -860,6 +896,7 @@ def load(self, uifile, *args, **kwargs):
# a RuntimeError.
etree = ElementTree()
etree.parse(uifile)
self._loadCustomWidgets(etree)

widget = Qt._QtUiTools.QUiLoader.load(
self, uifile, *args, **kwargs)
Expand Down Expand Up @@ -889,7 +926,8 @@ def createWidget(self, class_name, parent=None, name=""):
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)
Expand Down
66 changes: 66 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ def captured_output():
sys.stdout, sys.stderr = old_out, old_err


def CustomWidget(parent=None):
"""
Wrap CustomWidget class into a function to avoid global Qt import
"""
from Qt import QtWidgets

class Widget(QtWidgets.QWidget):
pass

return Widget(parent)


self = sys.modules[__name__]


Expand Down Expand Up @@ -197,6 +209,38 @@ def captured_output():
"""


qcustomwidget_ui = u"""\
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>238</width>
<height>44</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="CustomWidget" name="customwidget">
</widget>
</widget>
<customwidgets>
<customwidget>
<class>CustomWidget</class>
<extends>QWidget</extends>
<header>tests.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
"""


def setup():
"""Module-wide initialisation

Expand All @@ -216,6 +260,8 @@ def saveUiFile(filename, ui_template):
self.ui_qmainwindow = saveUiFile("qmainwindow.ui", qmainwindow_ui)
self.ui_qdialog = saveUiFile("qdialog.ui", qdialog_ui)
self.ui_qdockwidget = saveUiFile("qdockwidget.ui", qdockwidget_ui)
self.ui_qcustomwidget = saveUiFile("qcustomwidget.ui", qcustomwidget_ui)


def teardown():
shutil.rmtree(self.tempdir)
Expand Down Expand Up @@ -350,6 +396,26 @@ def test_load_ui_dockwidget():
app.exit()


def test_load_ui_customwidget():
"""Tests to see if loadUi loads a custom widget properly"""
import sys
from Qt import QtWidgets, QtCompat

app = QtWidgets.QApplication(sys.argv)
win = QtWidgets.QMainWindow()

QtCompat.loadUi(self.ui_qcustomwidget, win)

# Ensure that the derived class was properly created
# and not the base class (in case of failure)
custom_class_name = getattr(win, "customwidget", None).__class__.__name__
excepted_class_name = CustomWidget(win).__class__.__name__
assert custom_class_name == excepted_class_name, \
"loadUi could not load custom widget to main window"

app.exit()


def test_load_ui_invalidpath():
"""Tests to see if loadUi successfully fails on invalid paths"""
import sys
Expand Down