TEveManager, TGListTree & TEveListTreeItem

Dear forum,

I’m trying to override the “Checked” behaviour of TGListTree in TEveManager (actually, a derived class called TBBQManager). First I disconnect all signals:

gEve->GetListTree()->Disconnect("Checked(TObject*, Bool_t)");

and then connect my own signal handler:

   gEve->GetListTree()->Connect(
      "Checked(TObject*, Bool_t)",
      "TBBQManager",
      this,
      "slotTreeItemChecked(TEveListTreeItem*, Bool_t)"
   );

where TBBQManager is a derived class from TEveManager. The method slotTreeItemChecked is fairly simple for now:

void TBBQManager::slotTreeItemChecked(TEveListTreeItem* item, Bool_t check) {
   std::cout << "slotTreeItemChecked: " << item->GetText() << (check ? " Checked!" : " not Checked!") << std::endl;

   if (strcmp(item->GetText(), "All hits") == 0) {
      std::cout << "item is All hits" << std::endl;

      TEveElement* list = static_cast<TEveElement*>(item->GetUserData());

      std::cout << "ElementName: " << list->GetElementName() << std::endl;
   }
}

When executed it returns a seg violation on list->GetElementName(). Is there something wrong with the type cast? The implementation of TEveListTreeItem->GetText() is:

virtual const char     *GetText()          const { return fElement->GetElementName(); }

What is the difference between calling this GetText method and ((TEveElement*) GetUserData())->GetElementName()?

With regards,

Bon

Hi Bon,

The user-data of a list-tree-item points to a TEveElement … so your code should be ok.
How do you populate the list-tree?

The GetText() method returns what is to be displayed in the list-tree for each item … which is the name of the assigned element. So, there should be no difference.

By overriding the connection of the checked signal you disable the ability to toggle visibility of an element (and its children). I can hardly imagine a use-case where this would be beneficial. What are you planning to do with this?

Cheers,
Matevz

Hi Matevz,

Thank you for the reply.

The list-tree is populated by calling gEve->AddElement(someTEveElement).

After a bit of thought I came to the same conclusion that overriding that connection is not a good idea. What I intended to do is to link the “Checked” flag of the parent item to the “Checked” flag of the childrens. So when I check a parent, all the childrens are also checked. Any suggestions/ideas on how to implement that?

Apart from that, it is still strange that it gives me the seg violation. ROOT gives me the following backtrace

...
#6  0x00002ac6eafad694 in sighandler (sig=11) at core/unix/src/TUnixSystem.cxx:3428
#7  <signal handler called>
#8  0x00002ac6ea9f2b70 in vtable for TEveElementList () from /afs/cern.ch/sw/lcg/app/releases/ROOT/5.26.00b/x86_64-slc5-gcc43-dbg/root/lib/libEve.so
#9  0x00002ac6eaa73a9c in TBBQManager::slotTreeItemChecked(TEveListTreeItem*, bool) () from /afs/cern.ch/user/c/cblam/Projects/LCD/summerstudent/build/lib/libBBQ.so
...

With regards,

Bon

Hi Bon,

TEveElement has two separate visibility flags: SetRnrSelf(bool) and SetRnrChildren(bool). When clikcing on the check-box in the list-tree, both get flipped. By clicking on the element, you can set them individually in the object editor below.

Now, a child element is only drawn if:
a) it’s parent has RnrChildren set to true AND
b) the element has RnrSelf set to true.

So, what you want happens implicitly, just the check-boxes of children don’t show the state as you expect it.

SetRnrXyzz() functions are virtual in TEveElement – so if you are trying to do that for your own sub-class, you can override it there. Note that you will then have to recurse through all the structure.
What do you expect to happen when you turn the parent back on? To also show all the children? This is the tricky part … as you will lose the state of children if you do what you propose.

About the cast – it seems it goes wrong somewhere. Can you try with reinterpret_cast or plain C-style cast?

Cheers,
Matevz

Hi Matevz,

I’ve tried all casts without luck.

I’m sorry that I forgot to mention one big detail. The point is the following. I have a track (TEveTrack) that belongs to a certain collection (TEveElementList). I also want to add the same track to some “master” collection (TEveElementList) that is intended to have all tracks of all collections. In this way I’ll have two points of entry in the user interface for the visibility.

The intended behaviour should be:

  • The visibility of the childrens are independent of the parent’s flags.
  • The parents only propagate the state when the user checks the parent item in the list tree.

I think the suggestion of creating a sub-class for that and then override it is a very good one (I think it might be the solution, but let me see first). I’ll look into that. Fortunately it is a feature and not a requirement for my program so I can just skip this. But it still nags me for not being able to solve this problem!

Bon

Hi Bon,

Bummer, then I’d suggest building in debug mode and running in a debugger. You can recompile only EVE in debug mode:
cd $ROOTSYS
make clean-eve
ROOTBUILD=debug make

[quote=“cblam”]
The intended behaviour should be:

  • The visibility of the childrens are independent of the parent’s flags.
  • The parents only propagate the state when the user checks the parent item in the list tree.
    Bon[/quote]
    What will you do if the state of both parents is different / inconsistent?
    You could also put the sub-track containers into the all-track container.

[quote=“cblam”]
I think the suggestion of creating a sub-class for that and then override it is a very good one (I think it might be the solution, but let me see first). I’ll look into that. Fortunately it is a feature and not a requirement for my program so I can just skip this. But it still nags me for not being able to solve this problem!
Bon[/quote]

OK … let me know if you need help with this.

Cheers,
Matevz