[Kde-bindings] playground/bindings/kimono

Richard Dale richard.j.dale at gmail.com
Tue Mar 6 16:33:36 UTC 2007


On Tuesday 06 March 2007, Arno Rehn wrote:
> Am Dienstag, 6. März 2007 schrieb Richard Dale:
> > On Tuesday 06 March 2007, Arno Rehn wrote:
> > > Am Dienstag, 6. März 2007 schrieb Richard Dale:
> > > > On Tuesday 06 March 2007, Arno Rehn wrote:
> > > > > Am Montag, 5. März 2007 schrieb Richard Dale:
> > > > > > So the 'internalPointer' has a different value even when the
> > > > > > underlying instance is the same. That's because
> > > > > > QAbstractItemModel.CreateIndex() allocates a new GCHandle every
> > > > > > time, which will have different values. The reason it works in
> > > > > > QtRuby is because the internalPointer is a Ruby VALUE that is
> > > > > > the same for every createIndex call.
> > > > >
> > > > > Ah tanks. I added a Dictionary where all the GCHandles for
> > > > > QModelIndex'es are stored. This GCHandle is looked up for the
> > > > > specific QModelIndex and then passed to the C++ helper function.
> > > > > Selecting child items is no problem anymore. Up to now I thought
> > > > > GCHandle.Alloc() returns always the same value, but apparently it
> > > > > doesn't.
> > > >
> > > > I thought about have a WeakReference as a key, but I don't think that
> > > > works because wrapping an instance in a GCHandle will probably create
> > > > a strong reference (you wouldn't want an instance to be GC'd while
> > > > you were referencing it in C code).
> > >
> > > Yes, that's right, but than we just need to change the WeakReference to
> > > a normal, 'strong' reference.
> > >
> > > > So I think you need to have the actual object as a key, and a struct
> > > > as a value with two fields; a reference count and a GCHandle. When
> > > > you add a new GCHandle, set the ref count to 1 and increment every
> > > > time the handle is reused in another QModelIndex. Then in the
> > > > QModelIndex destructor, retrieve the entry for the wrapped object and
> > > > decrement the ref count. If the ref count is then zero, delete the
> > > > entry.
> > >
> > > That won't work, I think, because the destructor is only called
> > > automatically, when the object is GC'd. And as long as there is a
> > > strong reference, the object won't be GC'd, so the destrcutor is never
> > > called. Hence, the only case in which a destructor is called is when
> > > you have something like
> > > using (QModelIndex index = CreateIndex(...)) {
> > >       // code
> > > }
> >
> > No, there won't be a reference to the QModelIndex in the dictionary to
> > prevent it being GC'd, only to the thing inside the 'internalPointer' (ie
> > TreeItem or similar).
>
> But there will be a reference inside the GCHandle, you yourself said
> 'wrapping an instance in a GCHandle will probably create a strong reference
> (you wouldn't want an instance to be GC'd while you were referencing it in
> C code).'
> That would mean by creating a GCHandle to be stored in somewhere, we
> automatically create a strong reference to the object and thus prevent it
> from being GC'd. Without the GC calling the destructor of the object, we
> can't decrement anything. MSDN says the following to the GCHandleTypes:
>
> Normal (default):
> [...] You can use this type to track an object and prevent its collection
> by the garbage collector. [...]
>
> Weak:
> This handle type is used to track an object, but allow it to be collected.
> [...]
>
> That means, we could create a GCHandle with GCHandleType.Weak but there
> would be a danger of the object being GC'd while it is in use by C code
> (even though the probability of this is very small, I think).
> If we use GCHandleType.Weak, we can keep the code as it is at the moment,
> since nothing would prevent the GC from collecting the QModelIndex and if
> the weakRef is Zero ( = the object was collected) the entry is deleted.
>
> I hope we don't talk cross-purposes.
>
> > > After that the instance is gone, and then it wouldn't make sense
> > > anymore to decrement some counter, because the instance was deleted
> > > anyway.
> > >
> > > I think the current way is OK, because we can easily check if the
> > > instance is still alive (e.g. in the above example with using(...)
> > > {...} it may have been deleted) and if not, we can just delete the
> > > entry in the Dictionary. The WeakReference is just as good as a strong
> > > reference for this kind of doings and provides us with IsAlive a useful
> > > property.
> >
> > The key WeakReference will always be alive because the value has a
> > GCHandle wrapping the key.
>
> Oops, ok, that's right.
I just tried out my idea as code, and it doesn't work. Oh well. It gives this
output:

Can't select indexes from different model or with different parents
topLeft.model: 0x84ef070 bottomRight.model: 0x84ef070
topLeft.parent().row(): 5 topLeft.parent().column(): 0
bottomRight.parent().row(): 5 bottomRight.parent().column(): 0
topLeft.parent().internalPointer(): 0x79f3
bottomRight.parent().internalPointer(): 0x79d3
topLeft.parent().model(): 0x84ef070 bottomRight.parent().model(): 0x84ef070

So the two select points need to have the same parent still, although all the
details match. Hmm.. I don't understand how it works in Ruby now. I've
attached the patch of what I did anyway as that might be clearer than
trying to describe it.

-- Richard
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qmodel_index.patch
Type: text/x-diff
Size: 3128 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-bindings/attachments/20070306/6a02251c/attachment.bin>


More information about the Kde-bindings mailing list