QML TreeView collapse section when click different section - qt

I have a QML TreeView which expands / collapses branches upon click (builtin to treeview). However, when I expand one branch, I want other branches at the same depth to collapse. I've gotten as far as the code below which collapses ALL branches when an item is clicked.
How can I collapse ONLY branches which are NOT on the path from root index to the clicked index? (Either in C++ or JS)? So that it behaves like an accordion
In my TreeView:
onClicked: {
console.log(index)
for(var i=0; i < treemodel.rowCount(); i++) {
var nextIndex = treemodel.index(i,0)
if(mytreeview.isExpanded(nextIndex)) {
mytreeview.collapse(nextIndex)
}
}
}

Related

Is there a way to distinguish internally defined children from externally defined ones in QML?

I have defined a MyElement element (in the MyElement.qml file) as the following:
Rectangle {
Item {
}
Component.onCompleted: {
console.warn(children.length)
}
}
Let's call the Item element defined within MyElement the internal child. Now, I'm using the MyElement element in the following way:
MyElement {
Item {
}
}
Here another one Item element is used as a child of MyElement. Let's call this Item element the external child. To understand my question below one should clearly understand the difference between internal and external children.
The output for the presented code will be 2, i.e. both Item elements are calculated as children.
In the future I want to iterate in the block Component.onCompleted only over external children, not over internal (external children go after internal). But for this I have to know a children index from which I have to start (in the given example this index is 1). Is there a way to get this index or, in other words, the number of internal children? Thanks.
There is no internal mechanism in Qt to distinguish internal children from those which are defined outside of the own QML definition.
My workaround is as follow
//MyElement.qml
Rectangle {
id: root
readonly property Item last_item: lastone
Item {
id: someitem
}
Item {
id: lastone
}
Component.onCompleted: {
var external_started = false;
for(var i = 0 ; i < root.children.length ; ++i)
{
if(external_started)
console.log(root.children[i].toString(), 'is external');
else if(root.children[i]===last_item)
external_started = true;
}
}
}
and
MyElement {
Item {
objectName: 'I am external'
}
}
It's a dirty hack but it works.
I'm saving a reference to the last item in a readonly property called last_item and that will distinguish my last item in qml definition.
Other items which are added outside of the qml file, will be placed after this item in the children list.

How to remove grid children in a specific RowDefinition?

I'm drawing the controls dynamically at run time inside a grid. I want to clear all children under a specific control when the user taps on it. I have this but this only remove the RowDefinitions:
var currentRow = Grid.GetRow((BindableObject)sender);
for (int i = currentRow + 1; i < grdDynamic.RowDefinitions.Count; i++)
{
grdDynamic.RowDefinitions.RemoveAt(i);
}
but I need to clear all the grid children in those RowDefinitions.
This should remove the children in your grid with the tapped row as attribute.
var children = grdDynamic.Children.ToList();
foreach (var child in children.Where(child => Grid.GetRow(child) == row)) {
grdDynamic.Children.Remove(child);
}
It loops over all children in your grid and removes the child if its row equals the tapped row.

Dragged QGraphicsItem not visible in items() function

I have created a QGraphicsScene scene and added some graphcis items (lines, rectangles) etc to the scene.
I can loop through them using this list :
QList<QGraphicsItem*> all = items();
I enabled movement for these items and I am able to drag them by click selecting them. But after an element has been dragged, it stops showing up in the call to items() function of the QGraphicsScene.
QList<QGraphicsItem*> all = items();
None of the dragged items show up in the above list, while non-dragged ones do show up.
Does dragging the QGraphicScene elements change their parent ? or any other reason somebody could suggest for such an issue ?
{P.S. Code is too very big to share}
Edit 1 :
I am using the flags QGraphicsItem::ItemIsSelectable and QGraphicsItem::ItemIsMovable for making the items movable.
foreach(QGraphicsItem* itemInVisualScene, items())
{
itemInVisualScene->setFlag(QGraphicsItem::ItemIsSelectable, itemsMovable);
itemInVisualScene->setFlag(QGraphicsItem::ItemIsMovable, itemsMovable);
}
By default I add few rectangle to the scene. Then in the 'move mode' I drag them around. Then in the 'add mode' I click on screen to add new rectangles. I have written a logic to check if I am clicking on any existing drawn rectangle :
void Scene::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
if(eDrawLines == sceneMode)
{
dragBeginPoint = event->scenePos();
dragEndPoint = dragBeginPoint;
QList<QGraphicsItem*> all = items();
for (int i = 0; i < all.size(); i++)
{
QGraphicsItem *gi = all[i];
// Clicked point lies inside existing rect
if( QGraphicsRectItem::Type == gi->type() && gi->contains(dragBeginPoint))
{
std::cout << "Pressed inside existing rect" << std::endl;
return;
}
}
std::cout << "Point not found, add new rectangle" << std::endl;
}
QGraphicsScene::mousePressEvent(event);
}
This adding of rectangles work fine for rects which were not dragged in the 'move mode'. But rects which were moved do not seem to recognize the click anymore. My control comes out of the loop even when I click on an existing rectangle which was dragged earlier.
QGraphicsItem's transform is changed after dragging and therefore need to transform the point to item's local coordinates.
gi->contains(gi->mapFromScene(dragBeginPoint))
To convert or get item's position in scene coordinates, use
gi->mapToScene(0,0) or gi->scenePos()

GWT - Styling TreeItems

in my application I have a tree structure made out of treeitems.
What I wanted to do was change the background of certain tree items if their userObject satisfies certain conditions. The problem I have is when a root tree item is getting its background changed (only tested it on criteria being satisfied at tree items at the root level), all child treeitems of that tree item also have their background changed despite me going in and removing that style sheet on the children.
Long story short: I want it to only change the background on the tree item itself, and not its children.
code:
if(item.getUserObject() != null && ((Device)item.getUserObject()).getDeviceType() == type)
{
item.setStyleName("labelHighlight");
}
else
{
item.removeStyleName("labelHighlight");
}
for(int i = 0; i < item.getChildCount(); i++)
{
highlightNodes(type, item.getChild(i));
}
Use a widget instead of directly styling treeItem. Like this, you can change background of your widget and not the background of all your tree item

Flex 4 spark List width resize issue

I've got a spark List with an item renderer. When I click on an element, the renderer becomes larger and when I click again, it becomes small again.
The problem is that list doesn't resize with the content. I've tried to dispatch an event from the renderer passing its content size and resize list in this way:
private function refreshList(event:ResultEvent):void
{
var size:Number = (event.result as Number) + 6;
if (size >= mylist.width)
{
consultingNumber++;
mylist.width = size;
}
else
{
consultingNumber--;
if (consultingNumber == 0)
mylist.width = size;
}
mylist.invalidateDisplayList();
}
consultingNumber is the number of 'opened' renderer.
It works quite well, but when all renderer is 'closed' an horizontal scrollbar appear.
Tracing list's width it result correct but the scrollbar is there even if I set horizontalScrollPolicy to off.
Try calling myList.invalidateSize() instead of myList.invalidateDisplayList();
Here is some more information about the flex component lifecycle which should get you on the right track:
http://weblog.mrinalwadhwa.com/2009/06/21/flex-4-component-lifecycle/
http://www.slideshare.net/rjowen/adobe-flex-component-lifecycle-presentation
Cheers

Resources