PySide Bugzilla Closed for New Bugs

PySide is now a Qt Add-on and uses the Qt Project's JIRA Bug Tracker instead of this Bugzilla instance. This Bugzilla is left for reference purposes.

Bug 533 - Overriding event handlers of widgets loaded by QUiLoader fails
: Overriding event handlers of widgets loaded by QUiLoader fails
Status: CLOSED INVALID
Product: PySide
Classification: Unclassified
Component: QtUiTools
: 1.0.0 beta1
: PC All
: P4 critical
Assigned To: renato filho
:
:
:
  Show dependency treegraph
 
Reported: 2010-12-07 07:21 EET by Krzysztof Wlodarczyk
Modified: 2011-01-06 16:25 EET (History)
8 users (show)

See Also:


Attachments
test source (335 bytes, text/x-python)
2010-12-07 07:21 EET, Krzysztof Wlodarczyk
Details
the ui (392 bytes, application/octet-stream)
2010-12-07 07:21 EET, Krzysztof Wlodarczyk
Details
Updated test with custom widgets (449 bytes, text/x-python)
2010-12-18 16:08 EET, Lauro Moura
Details
Updated ui file (396 bytes, application/x-designer)
2010-12-18 16:08 EET, Lauro Moura
Details
test with two custom widgets (694 bytes, text/x-python)
2010-12-20 11:13 EET, Krzysztof Wlodarczyk
Details
ui for the 1st custom widget (397 bytes, application/x-designer)
2010-12-20 11:14 EET, Krzysztof Wlodarczyk
Details
ui for the 2nd custom widget (403 bytes, application/x-designer)
2010-12-20 11:15 EET, Krzysztof Wlodarczyk
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Wlodarczyk 2010-12-07 07:21:09 EET
Created attachment 168 [details]
test source

Overriden event handlers of widgets loaded by QUiLoader.load() are never
called.


import sys
from PySide import QtCore, QtGui
from PySide.QtUiTools import QUiLoader


app = QtGui.QApplication([])

window = QUiLoader().load("widget.ui")  #widget 1
#window = QtGui.QWidget()               #widget 2

window.closeEvent = lambda event: sys.stdout.write("CLOSING\n")
window.showEvent = lambda event: sys.stdout.write("SHOWING\n")

window.show()
app.exec_()



Nothing is printed if widget 1 is uncommented instead of widget 2.
Comment 1 Krzysztof Wlodarczyk 2010-12-07 07:21:58 EET
Created attachment 169 [details]
the ui
Comment 2 Matti Airas 2010-12-07 08:28:47 EET
Thanks for the bug report. This indeed is pretty awkward and reduces the
usability of QtUiTools quite a bit. Prioritizing P2 - this will be taken as a
high-priority bug, probably in the next sprint.
Comment 3 Hugo Parente Lima 2010-12-07 14:59:58 EET
I don't know if is possible to solve this issue, I'll try to explain:

When a object, e.g.: QWidget is created by PySide it create instances of
QWidgetWrapper, not QWidget. QWidgetWrapper is a C++ class which just inherits
QWidget and have all virtual methods implemented, the implementation of each
virtual method redirect the virtual call to Python if the there's a Python
implementation otherwise calls the normal C++ method.

As the objects returned by QUiLoader().load() were created by Qt, not by
PySide, they are instances of QWidget, not QWidgetWrapper, so they don't have
the code to redirect the virtual method calls to Python and your code don't
work.

The only way to solve this is reimplement the load() method in python, but I
don't really know how much work is needed to do this, imo it's a P3 bug.
Comment 4 Matti Airas 2010-12-07 18:55:24 EET
OK, since the fix is much more complex than I thought, let's take a timeout and
do as Hugo suggested - reprioritizing P3.
Comment 5 Matti Airas 2010-12-08 10:32:59 EET
Hugo, is this related in any way to bug 360?

Also, can Tamas Bajusz's loadUi replacement be used as a workaround?

http://www.mail-archive.com/pyside@lists.openbossa.org/msg00878.html

Sorry, asking stupid questions without doing proper backgroun research myself.
:-)
Comment 6 Hugo Parente Lima 2010-12-08 14:01:37 EET
(In reply to comment #5)
> Hugo, is this related in any way to bug 360?

No, not related.

> Also, can Tamas Bajusz's loadUi replacement be used as a workaround?
> 
> http://www.mail-archive.com/pyside@lists.openbossa.org/msg00878.html

No, it has the same problem: "Widgets created by Qt, not PySide".

I thought about our QtUiTools bindings and I got to the conclusion that was a
mistake to create bindings for them instead of do the same approach used by
PyQt4.

Was a mistake because QtUiTools bindings does not provides the same
funcionalities of the Python module used by PyQt4 to load .ui files besides the
creation of yet another incompatibility between PySide and PyQt4.

I think we still able to fix it, the python module used to load .ui codes is
LGPL and was written by the same guy who wrote the pyuic4 program, so we can
include them in PySide and just deprecate the QtUiTools binding, well... anyway
I think is better to open this discussion on the mailing list rather than here.

> Sorry, asking stupid questions without doing proper backgroun research myself.
> :-)

Nah, don't worry.. and the question wasn't stupid.
Comment 7 Matti Airas 2010-12-17 11:11:55 EET
Due to the design issues in QUILoader, we need to reimplement it, but this is
post-1.0 content. For now, we recommend to process the .ui files with
python-uic to create .py UI descriptions and import them.

I'm reprioritizing this to P4.
Comment 8 renato filho 2010-12-17 20:35:45 EET
In my opinion this is not a bug. You can have others problems if you implement
this function in Python and more code might be necessary to fix and fix this.

One example is:

if you have any QDialog and try to replace the "closeEvent" function used by
Dialog CloseButton (which is created on C++ side) this will fail in the same
way.


The the solution for your problem is:
Replace the closeEvent and showEvent is using a CustomWidget and use that on
your ui file. You can check more information on QUiloader documentation.
Comment 9 Matti Airas 2010-12-17 20:51:26 EET
Renato, could you give an example how to fix Krzysztof's sample code with your
suggested approach.
Comment 10 Lauro Moura 2010-12-18 16:08:31 EET
Created attachment 191 [details]
Updated test with custom widgets
Comment 11 Lauro Moura 2010-12-18 16:08:54 EET
Created attachment 192 [details]
Updated ui file
Comment 12 Lauro Moura 2010-12-18 16:14:12 EET
(In reply to comment #9)
> Renato, could you give an example how to fix Krzysztof's sample code with your
> suggested approach.

I've added an updated example that uses Renato's approach. The basic idea is
creating a QWidget-derived class with any customized behavior you want and
making the UiLoader call it instead of the C++ class.

Btw, +0.5 for replacing QUiLoader with the uic approach.
Comment 13 renato filho 2010-12-18 18:44:50 EET
the uic approach does not resolve all the problems to, and is a workaround more
ugly in my opinion.

I think this Krzysztof Wlodarczyk example, does not work with PyQt. Then I
think this is not a valid bug.

If you consider this a bug then you need consider this other example as a bug
too.

from PySide import QtGui
import sys

app = QtGui.QApplication([])
dlg = QtGui.QInputDialog()
dlg.show()
lbl = dlg.children()[0]
lbl.closeEvent = lambda event: sys.stdout.write("CLOSING\n")
lbl.showEvent = lambda event: sys.stdout.write("SHOWING\n")
app.exec_()


My point is, we can't encourage the use of this kind of virtual replacement,
because this wont work in all cases. I know this is a python way to do. But the
C++ bindigns have some limitations and this need be respect otherwise you can
have a very ugly code, because is hard to decide if this will work or not. 

Then use use the correct way and be happy.
Comment 14 Krzysztof Wlodarczyk 2010-12-20 11:13:33 EET
Created attachment 195 [details]
test with two custom widgets
Comment 15 Krzysztof Wlodarczyk 2010-12-20 11:14:29 EET
Created attachment 196 [details]
ui for the 1st custom widget
Comment 16 Krzysztof Wlodarczyk 2010-12-20 11:15:04 EET
Created attachment 197 [details]
ui for the 2nd custom widget
Comment 17 Krzysztof Wlodarczyk 2010-12-20 11:15:52 EET
I followed the approach that Renato suggested and unfortunately and I found out
that it doesn't work when loading multiple custom widgets.
I created a custom QWidget and a custom QDialog. After the first custom widget
is successfully loaded, calling the second load() throws an error:

"QFormBuilder was unable to create a widget of the class 'CustomDialog'."
Traceback (most recent call last):
  File "test3.py", line 28, in <module>
    dialog = loader.load("dialog.ui")
RuntimeError: Unable to open ui file

When I load only the socond one, everythings goes fine.
I tried creating another instance of QUiLoader for the second widget but it
didn't help (It seems that it is a singleton). There is no info on
registerCustomWidget method in PySide documentation.
Comment 18 renato filho 2010-12-20 19:01:42 EET
Now this is a really bug:

I found the problem in QUTools plug in used by pyside (a dummy bug), fixed on
pyside commit:

commit 5b6d130ffac1c9982e603b359a1910e32115c1cd
Author: Renato Araujo Oliveira Filho <renato.filho@openbossa.org>
Date:   Mon Dec 20 18:55:02 2010 -0300
Comment 19 Hugo Parente Lima 2011-01-05 15:01:03 EET
Anyone disagree marking this bug as INVALID?
Comment 20 Matti Airas 2011-01-06 06:22:13 EET
No, we have bug 553 to deal with the documentation issue, and while the
reported behaviour is somewhat unexpected from end-user's POV, it's the same as
in C++ and there are no easy ways to circumvent it. I'm resolving it now.
Comment 21 renato filho 2011-01-06 16:25:23 EET
released on beta3