PDA

View Full Version : Not able to see plus/tree sign for tree item when build child items dynamically



prasad_N
23rd July 2015, 21:31
Hi,

I don't want to use tree items for my tree view so I have designed my model as below.

I need to build tree based on 0's & 1's
All zeros are top level items, and 1's followed by 0 are child's for 0 & all 2's followed by 1 are child's of 1.



class Model : public QAbstractItemModel {

Q_OBJECT
public:
//all necessary functions for model
private:
mutable QVector<int> m_vector;
mutable QVector< QVector<int> > childs; // childs for top level items ex: if vector of vectors is [1 1 1] [1 1 1] [1 1 1] -> 1st top level items has 3 child's & 2nd, 3rd top level items also have 3 childs
};


So my model is:


int Model::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid()){
return 5000; // 5000 top level items
}
else if(!parent.parent().isValid()) //limited to 2 levels
{
return childs.at(parent.row()).count(1); // count no.of 1's for top level items which are 0 initially but when data() called there I am inserting 2 child's (1's), so when next time rowCount() is called it returns 2, but first time it would be 0. I am doing this because rowCount() calls for all the top level items initially that time I am simply passing 0, but again when data() is called rowCount() will be called one more time (for visible items only) that time I am inserting 2 items for top level item in data() function so rowCount() will return 2 this time.
}
return 0;
}

QVariant Model::data(const QModelIndex &index, int role ) const
{
if(index.isValid()){
QVector<int> row;
row << 1 << 1;
childs[index.row()] = row; // for all top level items inserting 2 child's
}

if(role == Qt::DisplayRole)
return index.row()+1;

return QVariant();
}



But my problem is I am not able to see plus sign for all the top level items in tree view (except 1st top level item).
But if i double click on visible top level item it is expanding with 2 child's (as expected) but there is no + sign which indicates that there are child's.
I implemented hasChildren() also and checked it did not work.

Any idea/suggestions for this ?? (I tested this with Qt4.8.6 & 5.4.0 on windows8)
Thanks in advance.

My complete model is here, if any one want to test:


Model::Model(QObject *parent): QAbstractItemModel(parent)
{
childs.resize(5000);
}

Model::~Model()
{
}

bool Model::hasChildren(const QModelIndex &parent) const
{
if(!parent.isValid())
return true;
if(!parent.parent().isValid()){
int val = childs.at(parent.row()).count(1);
return ( (0 != val) ? true : false);
}
return false;
}

QVariant Model::data(const QModelIndex &index, int role ) const
{
if(index.isValid()){
QVector<int> row;
row << 1 << 1;
childs[index.row()] = row;
}

if(role == Qt::DisplayRole)
return index.row()+1;

return QVariant();
}

int Model::columnCount(const QModelIndex &parent) const
{
return 1; //m_head.size();
}

int Model::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid()){
return 5000;
}
else if(!parent.parent().isValid()) //limited to 2 levels
{
return childs.at(parent.row()).count(1);
}
return 0;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if(!parent.isValid())
{
return createIndex(row, column, -1); // top level item has invalid parent
}
// we only need id of the parent since it identifies the item
return createIndex(row, column, parent.row());
}

QModelIndex Model::parent(const QModelIndex &ind) const
{
if(!ind.isValid()) return QModelIndex();
int id = ind.internalId();
if( id == -1) return QModelIndex();
return index(id, 0); // return top-level item
}

prasad_N
24th July 2015, 15:02
Any help or suggestions from Qt experts please ??

d_stranz
25th July 2015, 00:14
QTreeView::setRootIsDecorated() might help. It is true by default. Did you set it to false somewhere?

ChrisW67
25th July 2015, 01:12
The visibility of the tree expansion decoration ⊞ is controlled by the number of children the item has. No children, no indicator. You do not create the children until the first time the data() function is called (on any item for any reason, almost certainly not right). If the view calls hasChildren() or rowCount() before it calls data() then you have no children hence no indicator.

Your model is peculiar to say the least. If you want all the 5000 top level items to have default children then simply create them at construction time and return the vector count() for rowCount().

prasad_N
25th July 2015, 07:22
QTreeView::setRootIsDecorated() might help. It is true by default. Did you set it to false somewhere?

No where d_stranz.

Added after 15 minutes:


The visibility of the tree expansion decoration ⊞ is controlled by the number of children the item has. No children, no indicator. You do not create the children until the first time the data() function is called (on any item for any reason, almost certainly not right). If the view calls hasChildren() or rowCount() before it calls data() then you have no children hence no indicator.
Your model is peculiar to say the least. If you want all the 5000 top level items to have default children then simply create them at construction time and return the vector count() for rowCount().

hmm.. I have a problem with model default implementation (http://www.qtcentre.org/threads/63038-rowCount()-is-calling-for-all-the-top-level-items?highlight=).

I have a lots of data (millions of rows, probably more than 70 million items which a view can not handle in single page).
hence i have considerable amount of delay (rowCount() calls for all the top level items initially). So decided not to have any calculations rowCount().
if I want to build tree with tree items which is taking considerable amount time as data is in billions.
I can not go for lazy population because I will have problem with scroll bar size then(scroll size will be adjusted as we load data).


So I am looking for a way where I can load data dynamically(with correct scroll bar size at first time only), Any suggestions ??
With the above approach I felt some how I did it but not able to see plus sign even though I could see children with double click on parent.

Thanks a lot.

d_stranz
26th July 2015, 18:50
With the above approach I felt some how I did it but not able to see plus sign even though I could see children with double click on parent.


Probably because the chronology of events following the double-click results in the model reporting that the parent you clicked on has children (i.e. rowCount() > 0), and so the tree expands.

Face it, you are trying to use the model/view architecture in a way it wasn't designed for. In order for the parent items at any level in the tree to display arrow icons, they have to report that they have a non-zero row count. In order for the scrollbars to work correctly, the number of top-level items must be known at the time the tree is laid out in response to a change in the model. And all of this depends on the model correctly reporting all the details the tree view needs to lay itself out. By lying to the tree view about the size of the model, you are preventing it from working as designed and you end up with undesirable behaviour.

I've been reading your posts since you first started them a while back, and I can't help but think that whoever is putting together the specification for the code you are writing doesn't really understand what they are asking for. In practical terms, no one will ever scroll through a list of 70 million items, whether it is in a table or tree or whatever. So to start a user interaction with the premise that they will do a search and then drill down through 70 million answers to get to the subset they are really interested in not practical. Humans are not very good at seeing details in a sea of similar things. Giving them a huge list of things, all of which look basically the same, and expecting them to find the one they are most interested in will be a very tedious and frustrating experience. Faced with that kind of interface, I think users would quickly abandon the software for something less unwieldy.

On the other hand, humans are very good at detecting patterns and comparing images. Images are a great way of condensing a huge amount of information into something a human can look at and compare one result against another.

So instead of building a list of 70 million things, are there ways to display these results as some form of image or plot? Take a one-dimensional list and turn it into something where similar results are grouped together in 2D and things that are not so similar stand out? Selecting something from that image builds the tree based on items in the vicinity of the selection and lets the user drill down from there.

I don't know what field you are working in. I would guess it is possibly bioinformatics or demographics, but maybe not. Regardless, there has to be a more user-friendly way to present your results than what you are doing now.

prasad_N
28th July 2015, 18:54
Probably because the chronology of events following the double-click results in the model reporting that the parent you clicked on has children (i.e. rowCount() > 0), and so the tree expands.

Hmm.. its true.


I've been reading your posts since you first started them a while back,
glad to hear this :-)



I can't help but think that whoever is putting together the specification for the code you are writing doesn't really understand what they are asking for. In practical terms, no one will ever scroll thro.................................

Its true, may be I need to change my design & think in another way. But from my old posts I really did not get

1. why model should call all the top level items rowCount(), if it is for scroll bar its enough get to know rowCount() of invalid index. and get other items rowCount() when needed/scroll.
2. why should model call all the top level items rowCount() when we have variable headers.

I have already posted for the above problems. We have provided such a great MVC architecture, but not able to handle more data because of some reasons, hope they will get fixed in future version.

Thanks alot.