Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-12-09 Thread michael.brasser
On 25/11/2010, at 7:25 AM, ext Charley Bay wrote:
 This does raise the next question (or two):
 
 (1) The QML implies an instantiation tree of items in a parent-child 
 relationship.  That's great, and part of what makes QML so easy to use.  Is 
 this tree special in any way?  For example, if I dynamically create items, 
 or explicitly re-parent-items, are they treated differently in any way from 
 the ones hard-coded in the QML?  (I've observed strange behavior attempting 
 to re-parent a nested item that was hard-coded to a peer of the parent, 
 effectively removing it from its hard-coded parent.)

One difference is that the items created by the instantiation tree cannot be 
destroyed from QML (you cannot call destroy() on them the way you can for 
dynamically created items). I can't think of any differences in reparenting 
though -- do you remember what the strange behavior was that you observed?

 Fun stuff!  It works, and I'm happy.  However, I'd feel better if one of the 
 Trolls would comment that I'm doing acceptable as-designed practice, or if 
 I should think about doing this differently (e.g., how to implement a C++ 
 layout container operating on items dynamically added/removed from QML).


I'm not certain, but it's probably more of an optimization than anything else 
that ItemChildAddedChange is not triggered for items in the instantiation tree. 
If you haven't done so already, I'd suggest looking at the implementation of 
the QML positioners (Row, Column, Grid, etc) --  they layout all items (not 
just those added dynamically), but might give you some additional ideas for 
your layout container.

Regards,
Michael
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-27 Thread Charley Bay
snip, boundingRect() not working as expected?

Ummm... sorry to add confusion, but it is possible (seems likely to me) that
I observed an order of operations on initialization problem ...

I've re-structured my code, and now *both* the boundingRect() and
width/height properties work properly.

In the previous implementation, I had instantiation combined with
reparenting, and if the re-parenting happened before the instance was
fully constructed, then the size used during the re-parenting was incorrect
(the item later correctly resized itself after its attributes were set).
This is somewhat further complicated by the fact that setting attributes on
my QDeclarativeItem-derived types triggered signals for updates elsewhere.

It is interesting that I saw -1,-1 for default width/height before initial
size calculations, but I suppose that doesn't matter.

So... sorry for the confusion.  This has been a (very) good learning
exercise for me, though:  I think I better understand the dynamics of the
QDeclarativeItem (QObject) world as it relates to the QGraphicsItem
(non-QObject) world.

Thanks for the help!

--charley
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-26 Thread Charley Bay
Girish spaketh:

 boundingRect() works as I would expect. Can you provide some sample code?
 snip, example extracting good coordinates from
 QDeclarativeItem::boundingRect()


Was your C++ code inside an  application-derived
QDeclarativeItem::itemChange()?

I'm Qt4.7.0, Win7-64bit, MSVC++2008.

I tried it again to make sure there was no difference between my
dynamic_cast() and your qobject_cast(), and they behave the same.
(I suppose I should be doing qobject_cast anyway).

My code subset:

-
//FILE: MyQml.qml
import Qt 4.7
import MyPluginLayout 1.0

Rectangle {
  MyPluginLayout {
id: myPluginLayout
  }
  Text {
text: hello
parent: myPluginLayout
width: 40
height: 30
  }
}

-
//FILE: MyPluginLayout.cpp
class MyPluginLayout : public SdqDeclarativeItem
{
  ...Q_OBJECT, Q_PROPERTY, ...
  public:
virtual QVariant itemChange(
  QGraphicsItem::GraphicsItemChange change,
  const QVariant value)
{
  if(change == QGraphcisItem::ItemChildAddedChange)
  {
QGraphicsItem* graphics_item = value.valueQGraphicsItem*();
ASSERT(graphics_item);
//DEBUGGER SHOWS VTABLE FOR graphics_item TO BE A QDeclarativeText

QRectF bounding_rect;

bounding_rect = graphics_item-boundingRect(); // (0,0,-1,-1)
bounding_rect =
qobject_castQGraphicsObject*(graphics_item)-boundingRect(); //
(0,0,-1,-1)
bounding_rect =
qobject_castQDeclarativeItem*(graphics_item)-boundingRect(); //
(0,0,-1,-1)

double value;

value =
qobject_castQObject*(graphics_item)-property(width).toReal(); // 40
value =
qobject_castQObject*(graphics_item)-property(height).toReal(); // 30

value =
dynamic_castQObject*(graphics_item)-property(width).toReal(); // 40
value =
dynamic_castQObject*(graphics_item)-property(height).toReal(); // 30

//...do layout stuff to place item added...
   }
};
---

On the bright side, all of the boundingRect() calls agree.  They just don't
have the width/height property values.  So, I'm using QObject::property(),
which seems to always work.

--charley
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-24 Thread Charley Bay
snip, detect parent/child changes from QML in C++

Martin spaketh:

  QGraphicsItem::itemChange() may do what you want:



 http://doc.qt.nokia.com/4.7-snapshot/qgraphicsitem.html#itemChange


Works great!  Thanks!

Related question:  Now that I'm in the QGraphicsItem world, which is *not* a
QObject with properties, how does QML expose attributes (since those are
*all* properties based)?

For example, the QGraphicsItem::boundingRect() is always (0,0,-1,-1), even
though the referenced QML component *has* width and height.  Similarly, the
QGraphicsItem::opaqueArea()::boundingRect() is always (0,0,0,0).  Does the
QGraphicsItem have *any* opinion about or state from attributes in the QML
element?  (e.g., what attributes can I trust in the QGraphicsItem as being
those used by the QML element?)

What is the intended mechanism by which I interrogate the QGraphicsItem?
(Is the expectation that the user will merely attempt to downcast to
QGraphicsObject or QDeclarativeItem, handling the scenarios where it is not
that type?)  For examle, I *assume* that the MouseArea will trigger child
notification, but it is not a QDeclarativeItem.  In contrast, a Rectangle{}
or Text{} trigger child notification, and happen to be QDeclarativeItem
instances.

Thanks!

--charley
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-24 Thread Girish Ramakrishnan
Hi Charley,

On Wed, Nov 24, 2010 at 7:42 PM, Charley Bay charleyb...@gmail.com wrote:
 snip, detect parent/child changes from QML in C++

 Martin spaketh:

 QGraphicsItem::itemChange() may do what you want:



 http://doc.qt.nokia.com/4.7-snapshot/qgraphicsitem.html#itemChange

 Works great!  Thanks!

 Related question:  Now that I'm in the QGraphicsItem world, which is *not* a
 QObject with properties, how does QML expose attributes (since those are
 *all* properties based)?


QML works with properties exposed through the metaobject system
(Q_PROPERTY). So, items have to be extend QObject at some point.
AFAIK, QML supports properties exposed through QObject and user
visible items must be QGraphicsObject or QDeclarativeItem (there are
restrictions like the component's root item must be a QDeclarative
item etc).

 For example, the QGraphicsItem::boundingRect() is always (0,0,-1,-1), even
 though the referenced QML component *has* width and height.  Similarly, the
 QGraphicsItem::opaqueArea()::boundingRect() is always (0,0,0,0).  Does the
 QGraphicsItem have *any* opinion about or state from attributes in the QML
 element?  (e.g., what attributes can I trust in the QGraphicsItem as being
 those used by the QML element?)


QDeclarativeView builds on QGraphicsView. So,
QGraphicsItem::boundingRect is still very much used. For a component,
the QGraphicsItem of the component will return the (0, 0, width,
height), so I think your testing above is probably incorrect. I think
opaqueArea is used only for obscurity detection which is not used in
QML and thus left unimplemented.

 What is the intended mechanism by which I interrogate the QGraphicsItem?

As I understand, all QGraphicsItem API should still work as expected
for QML items.

 (Is the expectation that the user will merely attempt to downcast to
 QGraphicsObject or QDeclarativeItem, handling the scenarios where it is not
 that type?)  For examle, I *assume* that the MouseArea will trigger child
 notification, but it is not a QDeclarativeItem.  In contrast, a Rectangle{}
 or Text{} trigger child notification, and happen to be QDeclarativeItem
 instances.


MouseArea is a QDeclarativeItem. Think of it as a transparent
overlay child item that positions itself over the parent. I do not
know why it does not trigger child notifications.

Girish

___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-24 Thread Charley Bay
Ok, update, I couldn't wait to try this out (results below):

charley spaketh:

  Related question:  Now that I'm in the QGraphicsItem world, which is
 *not* a
  QObject with properties, how does QML expose attributes (since those are
  *all* properties based)?


 Giresh respondeth:

 QML works with properties exposed through the metaobject system
 (Q_PROPERTY). So, items have to be extend QObject at some point.
 AFAIK, QML supports properties exposed through QObject and user
 visible items must be QGraphicsObject or QDeclarativeItem (there are
 restrictions like the component's root item must be a QDeclarative
 item etc).


 Hmmm ... good point.  In theory, this means that *if* I could guarantee
 that all child notification events came from QML, I *should* be able to do a
 C++ cross-cast to cast my QGraphicsItem* to a QObject*, and then pull out
 my properties.

 Very interesting.  It will look a little weird, because QGraphicsItem has
 no base class, but I think it should work?  (I'll give it a try.)

 My original confusion was that I didn't know if it was appropriate to
 *assume* any castable type (e.g., from QGraphicsItem to a QGraphicsObject or
 QDeclarativeItem).  I'm still a little nervous about assuming the child
 event would be from any QObject type (that means my class would be usable
 fto interface from QML, and select C++ implementations) because the
 QGraphicsView would otherwise manage child QGraphicsItem instances (with no
 QObject in the hierarchy).  However, if that's the intended design, I could
 probably live with it.


The C++ cross-cast *WORKS* (Qt4.7.0,Win-Commercial,Win7-64bit,MSVC++2008):

QVariant MyClass::itemChange(QGraphicsItem::GraphicsItemChange change, const
QVariant value)
{
  if(change == QGraphicsItem::ItemChildAddedChange)
  {
 QGraphicsItem* graphics_item = value.valueQGraphicsItem*(); // ALWAYS
NON-NULL

 QObject* my_object = dynamic_castQObject*(graphics_item); // ALSO
NON-NULL FOR THIS CASE

 ...extracting properties from my_object works !!
  }
}

Looking in the debugger, the vtable for my_object is for a
QDeclarativeText, so I can see that it is my QML Text{} item.

Interestingly, the itemChange is NOT triggered for children explicitly
nested *within* the parent from QML, but *is* triggered for items explicitly
re-parented:

//FILE: MyQml.qml
Rectangle {
   MyCppClass {
  id: myCppClass
  Text { text: hello }  // DOES NOT TRIGGER
QGraphicsItem::itemChange()

  MouseArea {
anchors.fill:  parent
  }  // DOES NOT TRIGGER QGraphicsItem::itemChange()
   }

Text {
  text: world
  parent:  myCppClass  // YES, DOES TRIGGER QGraphicsItem::itemChange()
  }
}

For my particular case, this is accidentally a good thing:  I don't want
to re-parent the nested MouseArea, but I *do* want to re-parent any added
item (e.g., I'm implementing a layout-type container).

Because this accidentally works the way I want, I won't complain.  However,
if this is undocumented behavior, then I need to somehow test children
to see if they are something I want to parent (like Text{} items), versus
*not* parent (like nested MouseArea{} items).  This is acceptable to me:
I'll have to merely understand that I shouldn't be hard-coding Text{}
children with the assumption that the parent layout container will move them
(because it won't, because the QGraphicsItem::itemChange() won't be
triggered).

This does raise the next question (or two):

(1) The QML implies an instantiation tree of items in a parent-child
relationship.  That's great, and part of what makes QML so easy to use.  Is
this tree special in any way?  For example, if I dynamically create items,
or explicitly re-parent-items, are they treated differently in any way from
the ones hard-coded in the QML?  (I've observed strange behavior
attempting to re-parent a nested item that was hard-coded to a peer of the
parent, effectively removing it from its hard-coded parent.)

(2) If all children in memory are treated the same (e.g., (1) does not imply
that the different types of children are treated differently based on how
they are defined and instantiated), then this would imply some kind of
on-load-difference for firing signals, possibly related to order-of-load
(or connection of signals/slots after the items were loaded).  [Of course,
in this case, technically the hard-coded children were *not* re-parented,
but were merely hard-coded-parented, and the Trolls could merely state that
this was as designed behavior.]

 For example, the QGraphicsItem::boundingRect() is always (0,0,-1,-1), even
  though the referenced QML component *has* width and height.  Similarly,
 the
  QGraphicsItem::opaqueArea()::boundingRect() is always (0,0,0,0).  Does
 the
  QGraphicsItem have *any* opinion about or state from attributes in the
 QML
  element?  (e.g., what attributes can I trust in the QGraphicsItem as
 being
  those used by the QML element?)
 

 QDeclarativeView builds on QGraphicsView. So,
 

Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-24 Thread Girish Ramakrishnan
Hi,

On Thu, Nov 25, 2010 at 2:55 AM, Charley Bay charleyb...@gmail.com wrote:
 I confirmed that these *do not* work for me:

 ...with a Text { width: 50; height: 20 } on the QML side,

 QGraphicsItem::boundingRect() // ALWAYS RETURNS QRectF(0,0,-1,-1)
 QGraphicsItem::opaqueArea().boundingRect() // ALWAYS RETURNS QRectF(0,0,0,0)

 ...however, after casting the QGraphicsItem* to a QObject*, I can correctly
 extract my width and height properties.

 So, my current conclusion is that I have *no* useful properties in
 QGraphicsItem (and must cross-cast it to something I can use).

boundingRect() works as I would expect. Can you provide some sample code?

Rectangle {
width: 300
height: 300
objectName: rect

Text {
objectName: text
text: foo
}
}


QDeclarativeItem *rect = qobject_castQDeclarativeItem *(view-rootObject());
qDebug()  rect-boundingRect();
QDeclarativeItem *text = rect-findChildQDeclarativeItem *(text);
qDebug()  text-boundingRect();

Output:
QRectF(0,0 300x300)
QRectF(0,0 24x17)

The first one is the rect of the top level item (and it matches what I
set in qml) and the second one is the text item's computed
width/height. So, the values are as I would expect.

Girish
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml


Re: [Qt-qml] C++ MyClass to detect child added/removed from QML

2010-11-22 Thread martin.jones
QGraphicsItem::itemChange() may do what you want:

http://doc.qt.nokia.com/4.7-snapshot/qgraphicsitem.html#itemChange

Martin.

From: qt-qml-boun...@trolltech.com [mailto:qt-qml-boun...@trolltech.com] On 
Behalf Of ext Charley Bay
Sent: Tuesday, 23 November 2010 12:51 PM
To: qt-qml@trolltech.com
Subject: [Qt-qml] C++ MyClass to detect child added/removed from QML

I'm sure the answer is simple, but I can't find it:  I want my C++ implemented 
QML object to be notified when children are added:

//FILE: MyFile.qml
import Qt 4.7
import MyCppClass 1.0

Rectangle {
  MyCppClass {
id: myCppClass
Text { text: some text }   // CHILD NOT DETECTED AS ADDED
  }

  Text {
text: some other text
parent:  myCppClass  // CHILD NOT DETECTED AS ADDED
  }
}

In both the cases above, I'm unable to find a slot/notification/virtual 
function in the C++ implementation of MyCppClass that I can use to detect these 
children that are added.

Since MyCppClass derives from QDeclarativeItem, I see that it is a 
QGraphicsObject, mulitply-derived from from both QObject and QGraphicsItem.  I 
stumbled onto virtual QObject::childEvent(QChildEvent*) which looked ideal 
(since QChildEvent has child add/remove info), but it's not called in either of 
the cases above.

Then, digging into the Qt docs, I see that QGraphicsObject users should *NOT* 
look to QObject for parent/children relationships, but rather, should look only 
to QGraphicsItem.  Seems reasonable.  Unfortunately, I could not find anything 
in QGraphicsItem that looked like a slot or virtual function I could override 
to receive add/remove child notification events (I need both).

I'm sure this is a simple answer -- what notification does QML trigger that I 
can catch on the C++ side for (re-)parenting?

Thanks!

--charley
___
Qt-qml mailing list
Qt-qml@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml