2 Attachment(s)
Always show QTreeview branches in the far left column
I'm working with a Qtreeview and I'm facing some problems having the treview shown when either the first column is hidden or when I rearrange the tree.
I'm using a custom model where I've tried to put in a 'branch column' (m_branchcolumn see below) to map the parent to the first visible column in the treeview but it doesn't work. I always see the treeview nodes (the plus and minus signs) in column zero. I'm using an internal record representation like the nodeitem from the simple treeview example shipped with Qt.
Code:
{
if (!child.isValid())
Record *rec = recordFromIndex(child);
if (!rec)
Record *parentRecord = rec->parent;
if (!parentRecord)
if(parentRecord == rootRecord)
Record *grandparentRecord = parentRecord->parent;
if (!grandparentRecord)
int row = grandparentRecord->children.indexOf(parentRecord);
return createIndex(row, m_branchcolumn, parentRecord);
}
How can I make sure always to show the tree branches in the far left visible column even after column change and with hidden columns?
Re: Always show QTreeview branches in the far left column
By definition QTreeView displays branches in the column with logical index '0' (or the lowest non-hidden column probably but I'm not sure). To override that you have to either provide a proxy model that will rearrange your columns or reimplement QTreeView.
Re: Always show QTreeview branches in the far left column
Thanks for your reply wysota
Quote:
Originally Posted by
wysota
By definition QTreeView displays branches in the column with logical index '0' (or the lowest non-hidden column probably but I'm not sure).
Yes, QTreeview displays branches in the column with logical index '0' but if that column is hidden the tree nodes will not appear. Tree effect is preserved however as the user is still able to expand/subtract with plus and minus keys.
Quote:
Originally Posted by
wysota
To override that you have to either provide a proxy model that will rearrange your columns or reimplement QTreeView.
Acctually I am using a proxymodel for the treeview already. How would I go about rearranging the columns to get the effect I want?
Thanks
Re: Always show QTreeview branches in the far left column
The easiest would be to reimplement data() and call the base class implementation of the proxy with a modified index (switched column numbers).
Re: Always show QTreeview branches in the far left column
This is my reimplementation! I've tried to change the index but as it's a const function all my changes resolves in error. What would I need to change in this data function to swap say column 0 with column 1?
Code:
{
if (!index.isValid())
}
Thank you again for your help!
Re: Always show QTreeview branches in the far left column
Create a new index, don't change the original one (it's const...).
For example:
Code:
QModelIndex changed
= index.
sibling(index.
row(),
(index.
column()+1) % 10);
Re: Always show QTreeview branches in the far left column
It definitely one way to go but it gets messy. If I make changes to the 0 column the changes will be saved in the 'swap' column. Eventually I'll have to accommodate this change in index, parent, mapToSource, mapFromSource aswell right?
Below I'm substituting the branch column with 0 column and vica versa.
This is my new implementation;
Code:
{
if (!index.isValid())
if(index.column() == m_branchcolumn)
{
}
if(index.column() == 0)
{
QModelIndex changed
= index.
sibling(index.
row(), m_branchcolumn
);
}
}
I haven't gotten it to work correctly yet but I think this might be the way forward. Thanks for you input.
Re: Always show QTreeview branches in the far left column
Quote:
Originally Posted by
Nightfox
It definitely one way to go but it gets messy. If I make changes to the 0 column the changes will be saved in the 'swap' column. Eventually I'll have to accommodate this change in index, parent, mapToSource, mapFromSource aswell right?
It depends on your model.
Re: Always show QTreeview branches in the far left column
The model is a reimplemented QAbstractProxyModel. This shows you the functions I've reimplemented so far.
Code:
virtual int columnCount
(const QModelIndex
& parent
= QModelIndex()) const ;
virtual int rowCount(const QModelIndex& parent) const ;
virtual QModelIndex parent
(const QModelIndex
& index
) const ;
virtual QModelIndex mapFromSource
(const QModelIndex
&) const ;
virtual QModelIndex mapToSource
(const QModelIndex
&) const ;
virtual Qt
::ItemFlags flags
( const QModelIndex & index
) const;
Surely I need to swao the index for all these functions?
Re: Always show QTreeview branches in the far left column
If you are already implementing a proxy model then everything is just a matter of adjusting your mapFromSource() and mapToSource() methods. In the other methods you surely already use those two so everything should work fine.
Re: Always show QTreeview branches in the far left column
This gets more and more messy! I've implemented this to swap column 0 with the branch column in order to always have the branches in the far left column, even after user column rearrange.
However after the change in mapFramSource and mapToSource no data is displayed in the tree.
Code:
QModelIndex MyProxyModel
::mapFromSource(const QModelIndex
& sourceIndex
) const {
if (sourceIndex.isValid())
{
int key
= sourceModel
()->data
(sourceModel
()->index
(sourceIndex.
row(), m_sourcekeycolumn,
QModelIndex()) ).
toInt() ;
Record *rec = internaltable->m_map.value(key);
int row = 0;
if(rec->parent)
row = rec->parent->children.indexOf(rec);
const int brcol = getBranchColumn();
if( sourceIndex.column() == brcol ) {
QModelIndex changed
= sourceIndex.
sibling(row,
0);
//new return changed;
}
if( sourceIndex.column() == 0 ){
QModelIndex changed
= sourceIndex.
sibling(row, brcol
);
//new return changed;
}
return createIndex(row,sourceIndex.column(),rec) ;
}
}
//
QModelIndex MyProxyModel
::mapToSource(const QModelIndex
& proxyIndex
) const {
if(proxyIndex.isValid())
{
Record *rec = recordFromIndex(proxyIndex);
const int brcol = getBranchColumn();
if(rec)
{
if( proxyIndex.column() == brcol ) {
QModelIndex changed
= proxyIndex.
sibling(proxyIndex.
row(),
0);
//new return changed;
}
if( proxyIndex.column() == 0 ){
QModelIndex changed
= proxyIndex.
sibling(proxyIndex.
row(), brcol
);
//new return changed;
}
}
}
}
My model hieracy is QStandarItemModel to QAbstractProxyModel to QSortFilterProxyModel so the source model for the treeview is QSortFilterProxyModel. Why can't I squeeze more functionality out of the two extra proxy models to archive the column swap? I had really hoped for more help from one of the proxies!
What an I doing wrong?
Re: Always show QTreeview branches in the far left column
I am not sure if I correctly understood the task but is it not be easier to manipulate QHeaderView?
For example.
Code:
QFileSystemModel *model = new QFileSystemModel(ui->m_tv);
model->setRootPath("C:\\");
ui->m_tv->setModel(model);
int sectionCount = ui->m_tv->header()->count();
qDebug() << "Section count:" << sectionCount;
hv->moveSection(hv->visualIndex(0), hv->visualIndex(sectionCount - 1));
hv->setSectionHidden(hv->logicalIndex(1), true);
Re: Always show QTreeview branches in the far left column
Quote:
Originally Posted by
Rembobo
I am not sure if I correctly understood the task but is it not be easier to manipulate
QHeaderView?
No, because this causes tree branches to move.
Re: Always show QTreeview branches in the far left column
So I just spend like five days figuring out that the indexes of the proxymodel get changed when I add an additional model on top of that. I've been debugging and debugging and debugging to I almost gave up. You out there who knew this please don't say I told you so!
@wysota: I used you suggestion on changing the mapFromSouce and mapToSource functions and now it finally works! I'm able to have the tree branches in the m_branchcolumn column (see below). I dont know if you still follow the code but I'm using a hierarchical model like the Qt's simple treeview example but instead of a Node class I'm using a Record class - but essentially it's the same. The m_branchcolumn column is the column of which I wish to swap the 0 column. Thanks again for your input and help!
So the following implementation will keep the branches in the m_branchcolumn.
Code:
QModelIndex ViewModel
::mapFromSource(const QModelIndex
& sourceIndex
) const {
if (sourceIndex.isValid())
{
int key
= sourceModel
()->data
(sourceModel
()->index
(sourceIndex.
row(), m_sourcekeycolumn,
QModelIndex()) ).
toInt() ;
Record *rec = internaltable->getRecord(key);
int row = 0;
int col = sourceIndex.column();
if(rec->parent)
row = rec->parent->children.indexOf(rec);
if(sourceIndex.column() == m_branchcolumn) col = 0;
if(sourceIndex.column() == 0 ) col = m_branchcolumn;
return createIndex(row,col,rec) ;
}
}
QModelIndex ViewModel
::mapToSource(const QModelIndex
& proxyIndex
) const {
if(proxyIndex.isValid())
{
Record *rec = recordFromIndex(proxyIndex);
if(rec) {
int col = proxyIndex.column();
if(proxyIndex.column() == m_branchcolumn) col = 0;
if(proxyIndex.column() == 0 ) col = m_branchcolumn;
return sourceModel
()->index
(rec
->sourcerow,col,
QModelIndex());
}
}
}
Re: Always show QTreeview branches in the far left column
Great that you made it work. I was following the thread all the time - I'm very interested in every topic related to proxy models.
BTW. "I told you so" ;)
Re: Always show QTreeview branches in the far left column
Thanks wysota & Nightfox, this helped me immensely.
There isn't much documentation on mapToSource or mapFromSource so here is the code I figured out.
This is useful for changing the order of the columns without using moveSection.
Next step is to patch in another model in to this proxyModel.
Code:
QModelIndex RoadProxyModel
::mapFromSource(const QModelIndex
& sourceIndex
) const {
if (sourceIndex.isValid())
{
int col = sourceIndex.column();
int row = sourceIndex.row();
row = baseMapToSource.row();
switch (col)
{
case WIShmemModel::ColTrkBat:
return index(row, ColTrkBat);
case WIShmemModel::ColExchgPad:
return index(row, ColExchgPad);
case WIShmemModel::ColLaneNo:
return index(row, ColLane);
...
default:
LOG_DBG("Uknown column %d", col);
}
}
}
QModelIndex RoadProxyModel
::mapToSource(const QModelIndex
& proxyIndex
) const {
if(proxyIndex.isValid())
{
int row = proxyIndex.row();
row = baseMapToSource.row();
switch (proxyIndex.column())
{
case ColTrkBat:
return sourceModel()->index(row, WIShmemModel::ColTrkBat);
case ColExchgPad:
return sourceModel()->index(row, WIShmemModel::ColExchgPad);
case ColLane:
return sourceModel()->index(row, WIShmemModel::ColLaneNo);
...
default:
LOG_DBG("Uknown column %d", proxyIndex.column());
}
}
}