[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Re: [PyKDE] Issue with QDialog and lifetime
From:       "Phil Thompson" <phil () riverbankcomputing ! co ! uk>
Date:       2005-07-07 12:45:38
Message-ID: 30636.194.203.13.71.1120740338.squirrel () river-bank ! demon ! co ! uk
[Download RAW message or body]

> Phil Thompson <phil@riverbankcomputing.co.uk> wrote:
>
>>> The problem is that the idiomatic way of using modal dialogs in C++ is
>>> to
>>> create local variables, which gets destroyed when their scope finishes
>>> (when
>>> the function exits). Moreover, the dialogs have to be children of
> whatever
>>> widgets they are modal over (e.g. the main window).
>>>
>>> This has no direct translations in PyQt. If you do:
>>>
>>> def slotWhatever(self):
>>>    dlg = MyModalDialog(self)
>>>    if dlg.exec_loop() == QDialog.Accepted:
>>>        return dlg.data()
>>>    return None
>>>
>>> you are leaking "dlg" because its lifetime is bound to its parent. The
>>> current common workaround is something like:
>>>
>>> def slotWhatever(self):
>>>    dlg = MyModalDialog(self)
>>>    try:
>>>        if dlg.exec_loop() == QDialog.Accepted:
>>>            return dlg.data()
>>>        return None
>>>    finally:
>>>        dlg.deleteLater()
>>>
>>> which is ugly and error-prone (you have to remember to do it).
>>>
>>> James proposed this solution:
>>>
>>> def slotWhatever(self):
>>>    dlg = MyModalDialog(self)
>>>    sip.transfer(dlg, 0)
>>>    if dlg.exec_loop() == QDialog.Accepted:
>>>        return dlg.data()
>>>    return None
>>>
>>> and then proposed to hardcode the transfer() call within the
>>> %MethodCode
>>> for
>>> QDialog.exec_loop. I'll remember you that exec_loop is called only for
>>> modal
>>> dialogs, while for modeless dialogs show() is called.
>>
>> I'm uncomfortable with this for two reasons...
>>
>> 1. It's inconsistent behaviour. As there are things you need to be aware
>> of when using PyQt (particularly with regard to ownership) I think it's
>> important to have consistency in those things.
>>
>> 2. It creates the strong possibility of a seg fault for those (existing)
>> applications that don't follow the common idiom.
>
> Yeah, I understand. Better ideas?

1. Either add an optional parameter to exec_loop() which does the transfer
or have exec_loop_and_transfer() (or something less of a mouthful). At
least that way it won't break existing code.

2. Implement sip.destroy() which calls the C++ dtor of its argument. (This
is on the TODO list anyway.)

3. Use sip.transfer().

Either way, I don't think it can be done (to my satisfaction)
transparently. The programmer is going to have to be aware of the issue
and explicitly deal with it.

Phil

_______________________________________________
PyKDE mailing list    PyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic