Re: [PyKDE] Re: Bug with QScrollView viewport binding

2005-06-29 Thread Phil Thompson
On Wednesday 29 June 2005 3:21 pm, Giovanni Bajo wrote:
 Phil Thompson [EMAIL PROTECTED] wrote:
  Yes - but they aren't in existence at the same time.
  [...]
  Using a temporary name to keep a reference to sv.viewport() solves the
  problem.

 Then you have the inverse problem:

 --
 from qt import *

 app = QApplication([])
 sv = QScrollView(None)
 w = QWidget(sv.viewport())

 p = w.parent()
 print sv.viewport().width()
 --
 Traceback (most recent call last):
   File D:\Work\caligola3d\src\pyqtbug3.py, line 9, in ?
 print sv.viewport().width()
 AttributeError: width

 which is wrong because viewport() is supposed to return a QWidget pointer.

It sees that it has already been wrapped (as a QObject) and just returns an 
extra reference. It doesn't try to retype the existing wrapper, or create a 
new wrapper to the same C++ instance with the more specific type.

Phil

___
PyKDE mailing listPyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde


Re: [PyKDE] Re: Bug with QScrollView viewport binding

2005-06-29 Thread Giovanni Bajo
Phil Thompson [EMAIL PROTECTED] wrote:

 Yes - but they aren't in existence at the same time.
 [...]
 Using a temporary name to keep a reference to sv.viewport() solves the
 problem.

 Then you have the inverse problem:

 --
 from qt import *

 app = QApplication([])
 sv = QScrollView(None)
 w = QWidget(sv.viewport())

 p = w.parent()
 print sv.viewport().width()
 --
 Traceback (most recent call last):
   File D:\Work\caligola3d\src\pyqtbug3.py, line 9, in ?
 print sv.viewport().width()
 AttributeError: width

 which is wrong because viewport() is supposed to return a QWidget
pointer.

 It sees that it has already been wrapped (as a QObject) and just returns
an
 extra reference. It doesn't try to retype the existing wrapper, or create
a
 new wrapper to the same C++ instance with the more specific type.


I understand the technical problem, but I believe it is a right expectation
that any call to QScrollView.viewport() return a QWidget, as documented. The
fact that thousands lines away I happen to have a QObject reference to the
same object should not thoeretically make QScrollView.viewport() break its
contract.

Notice that there is *never* a need for downcast in PyQt, and this would be
a sole example. For instance:
--
 from qt import *
 app = QApplication([])
 class Foo(QWidget):
... k = 1
...
 f = Foo(None)
 w = QWidget(f)
 w.parent().k
1
 print w.parent()
__main__.Foo object at 0x00813660
--
In this case, PyQt was *even* able to recreate a wrapper of type Foo from
the parent call. I assume because the actual underlying type is something
that PyQt knows about (Foo) instead of an internal Qt type (as for the case
of the scrollview's viewport).

It is surprising that the call to parent() in the original example is not
able to return a QWidget. The common PyQt behaviour is always to return a
reference to most down-casted type. So I would expect the parent() to return
*at least* a QWidget whenever the object is a QWidget.

Either that, or always retry to downcast any reference you get from the
internal SIP map of existing python refernces. QScrollView.viewport() really
*is* supposed to return *at least* a QWidget.
-- 
Giovanni Bajo

___
PyKDE mailing listPyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde


Re: [PyKDE] Re: Bug with QScrollView viewport binding

2005-06-29 Thread Phil Thompson
On Wednesday 29 June 2005 4:07 pm, Giovanni Bajo wrote:
 Phil Thompson [EMAIL PROTECTED] wrote:
  Yes - but they aren't in existence at the same time.
  [...]
  Using a temporary name to keep a reference to sv.viewport() solves the
  problem.
 
  Then you have the inverse problem:
 
  --
  from qt import *
 
  app = QApplication([])
  sv = QScrollView(None)
  w = QWidget(sv.viewport())
 
  p = w.parent()
  print sv.viewport().width()
  --
  Traceback (most recent call last):
File D:\Work\caligola3d\src\pyqtbug3.py, line 9, in ?
  print sv.viewport().width()
  AttributeError: width
 
  which is wrong because viewport() is supposed to return a QWidget

 pointer.

  It sees that it has already been wrapped (as a QObject) and just returns

 an

  extra reference. It doesn't try to retype the existing wrapper, or create

 a

  new wrapper to the same C++ instance with the more specific type.

 I understand the technical problem, but I believe it is a right expectation
 that any call to QScrollView.viewport() return a QWidget, as documented.
 The fact that thousands lines away I happen to have a QObject reference to
 the same object should not thoeretically make QScrollView.viewport() break
 its contract.

Understood - but I'm concerned about possible unforeseen implications. Of the 
two obvious options...

1) Re-type the existing object when the more specific type is known. This is 
probably safe to do as far as the internals are concerned - but the idea of a 
Python object changing type under your feet sounds horrible.

2) Generate a new wrapper to the same C++ object with the more specific type. 
This has obvious problems with ownership (who calls the C++ dtor?), and 
things like is would fail. This is a real can of worms.

 Notice that there is *never* a need for downcast in PyQt, and this would be
 a sole example.

Some PyKDE uses have this requirement - hence sip.cast().

 For instance: 
 --

  from qt import *
  app = QApplication([])
  class Foo(QWidget):

 ... k = 1
 ...

  f = Foo(None)
  w = QWidget(f)
  w.parent().k

 1

  print w.parent()

 __main__.Foo object at 0x00813660
 --
 In this case, PyQt was *even* able to recreate a wrapper of type Foo from
 the parent call. I assume because the actual underlying type is something
 that PyQt knows about (Foo) instead of an internal Qt type (as for the case
 of the scrollview's viewport).

No, it's because f keeps the wrapper alive so it is found by w.parent().

 It is surprising that the call to parent() in the original example is not
 able to return a QWidget. The common PyQt behaviour is always to return a
 reference to most down-casted type. So I would expect the parent() to
 return *at least* a QWidget whenever the object is a QWidget.

The most down-cast type, yes - but *only* if it is a know type. Otherwise it 
resorts to the base type.

 Either that, or always retry to downcast any reference you get from the
 internal SIP map of existing python refernces. QScrollView.viewport()
 really *is* supposed to return *at least* a QWidget.

Yes - rather than see if the type *is* a known type, see if the type is 
*derived* from a known type. Or maybe do the second only if the first fails 
(for speed and to ensure it doesn't break existing behaviour).

Phil

___
PyKDE mailing listPyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde


Re: [PyKDE] Re: Bug with QScrollView viewport binding

2005-06-29 Thread Giovanni Bajo
Phil Thompson [EMAIL PROTECTED] wrote:

 I understand the technical problem, but I believe it is a right
 expectation that any call to QScrollView.viewport() return a
 QWidget, as documented. The fact that thousands lines away I happen
 to have a QObject reference to the same object should not
 thoeretically make QScrollView.viewport() break its contract.

 Understood - but I'm concerned about possible unforeseen
 implications. Of the two obvious options...

 1) Re-type the existing object when the more specific type is known.
 This is probably safe to do as far as the internals are concerned -
 but the idea of a Python object changing type under your feet sounds
 horrible.

 2) Generate a new wrapper to the same C++ object with the more
 specific type. This has obvious problems with ownership (who calls
 the C++ dtor?), and things like is would fail. This is a real can
 of worms.

I don't like either as well.

The current logic, quoting you, is:
 The most down-cast type, yes - but *only* if it is a know type.
 Otherwise it resorts to the base type.

Maybe this could be adjusted to: automatically cast-down to the most derived
type which is known. This way, calling parent() for QWidget's will always
create at least a QWidget, since all widgets' parents are widgets themselves.
Also, we would get a QWidget for the viewport too (which is derived from
QWidget, in fact), and this would solve the problem.

This is also what you say here, assuming I understood:

 rather than see if the type *is* a known type, see if the type
 is *derived* from a known type. Or maybe do the second only if the
 first fails (for speed and to ensure it doesn't break existing
 behaviour).

so looks like we agree on this solution.

 Notice that there is *never* a need for downcast in PyQt, and this
 would be a sole example.

 Some PyKDE uses have this requirement - hence sip.cast().

I would like to see some.

Giovanni Bajo

___
PyKDE mailing listPyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde