[Qt-interest] EditableTreeMode example crashing with modeltest
Daniel Price
daniel.price at fxhome.com
Tue Nov 24 14:44:15 CET 2009
Ok that makes sense.
I've added a check for that in rowCount(), which now returns 0 if the parent column is > 0 which now passes the first test! That's what the example Qt code was doing for index() but their rowCount() code is still wrong.
I think I've also found the problem with my inserts. The insertion code is column-sensitive. If you select the first column, and insert a row, all is fine. But if select the second, the code attempts to add the child to the second column (which as a result of the above change, cannot have children). This was masked by the face that my view was set to select rows, not items so it wasn't obvious that I was selecting the second column everytime.
You need to ensure that:
a) Regardless of the column selected, only the first column can have child nodes inserted.
b) QAbstractItemModel::insertRow(s) must return abort if the parent index column is anything other than zero!
This strangeness is the result of the treemodel being shoe-horned into a table-based framework, I think. It doesn't make sense for a tree to have 'columns' or for any column other than the first to have children (the modeltest checks this).
Thanks for your help!
-----Original Message-----
From: qt-interest-bounces at trolltech.com [mailto:qt-interest-bounces at trolltech.com] On Behalf Of Jan
Sent: 24 November 2009 11:45
To: qt-interest
Subject: Re: [Qt-interest] EditableTreeMode example crashing with modeltest
Daniel Price schrieb:
>> I suppose because if the column is > 0 it usually should not have a
>> parent (and therefore has no valid index) - only a sibling in column 0.
sorry, "should not have a *child*":
I suppose because if the column is > 0 it usually should not have a
*child* (and therefore has no valid index) - only a sibling in column 0.
If you have not changed the example except the part where you populate
the model I suppose there is something wrong with parenting the children
(just guessing though).
Jan
>
> My understanding is that each column is represented by a separate QModelIndex, accessible through the sibling() member function. But each column index must have the same parent otherwise how would QAbstractItemModel::index(row, column, parent) et al work?
>
>> Maybe make sure you provide as much item data as you have columns
>> (headers) in the root item
>
>> QVector<QVariant> rootData;
>> foreach (QString header, headers)
>> rootData << header;
>
> Yes I have done this. If I don't have data, I just get empty columns which I can edit.
>
> The assert is being triggered because the unit test is asking for the non-zero column-index of a valid row.
>
> I'm not sure if this is the cause of my original issue (inconsistency between the view and the model) but there is something very wrong here!
>
> Here is my adaptor in it's entirety (TreeNode is very similar to Qt's TreeItem):
>
> TreeModelAdaptor::TreeModelAdaptor(const QStringList &headers, QObject *parent)
> :
> QAbstractItemModel(parent),
> m_rootNode(NULL)
> {
> QVector<QVariant> rootData;
> foreach (QString header, headers)
> rootData << header;
>
> m_rootNode = new TreeNode(rootData);
> }
>
> TreeModelAdaptor::~TreeModelAdaptor()
> {
> delete m_rootNode;
> }
>
> QModelIndex TreeModelAdaptor::index(int row, int column, const QModelIndex &parent) const
> {
> if (parent.isValid() && parent.column() != 0)
> return QModelIndex();
>
> if (row < 0 || column < 0)
> return QModelIndex();
>
> TreeNode *parentNode = nodeFromIndex(parent);
>
> TreeNode *childNode = parentNode->child(row);
> if (childNode)
> return createIndex(row, column, childNode);
> else
> return QModelIndex();
> }
>
> QModelIndex TreeModelAdaptor::parent(const QModelIndex &index) const
> {
> if (!index.isValid())
> return QModelIndex();
>
> TreeNode *childNode = nodeFromIndex(index);
> TreeNode *parentNode = childNode->parent();
>
> if (parentNode == m_rootNode)
> return QModelIndex();
>
> return createIndex(parentNode->childNumber(), 0, parentNode);
> }
>
> int TreeModelAdaptor::rowCount(const QModelIndex &parent) const
> {
> TreeNode *parentNode = nodeFromIndex(parent);
>
> return parentNode->childCount();
> }
>
> int TreeModelAdaptor::columnCount(const QModelIndex &parent) const
> {
> return m_rootNode->columnCount();
> }
>
> QVariant TreeModelAdaptor::headerData(int section, Qt::Orientation orientation, int role) const
> {
> if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
> return m_rootNode->data(section);
>
> return QVariant();
> }
>
> Qt::ItemFlags TreeModelAdaptor::flags(const QModelIndex &index) const
> {
> if (!index.isValid())
> return 0;
>
> return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
> }
>
> QVariant TreeModelAdaptor::data(const QModelIndex &index, int role) const
> {
> if (!index.isValid())
> return QVariant();
>
> if (role != Qt::DisplayRole && role != Qt::EditRole)
> return QVariant();
>
> TreeNode *node = nodeFromIndex(index);
>
> return node->data(index.column());
> }
>
> bool TreeModelAdaptor::setData(const QModelIndex &index, const QVariant &value, int role)
> {
> if (role != Qt::EditRole)
> return false;
>
> TreeNode *node = nodeFromIndex(index);
> bool result = node->setData(index.column(), value);
>
> if (result)
> emit dataChanged(index, index);
>
> return result;
> }
>
> bool TreeModelAdaptor::insertColumns(int position, int columns, const QModelIndex &parent)
> {
> beginInsertColumns(parent, position, position + columns - 1);
> bool success = m_rootNode->insertColumns(position, columns);
> endInsertColumns();
>
> return success;
> }
>
> bool TreeModelAdaptor::removeColumns(int position, int columns, const QModelIndex &parent)
> {
> beginRemoveColumns(parent, position, position + columns - 1);
> bool success = m_rootNode->removeColumns(position, columns);
> endRemoveColumns();
>
> if (m_rootNode->columnCount() == 0)
> removeRows(0, rowCount());
>
> return success;
> }
>
> bool TreeModelAdaptor::insertRows(int position, int rows, const QModelIndex &parent)
> {
> TreeNode *parentNode = nodeFromIndex(parent);
>
> beginInsertRows(parent, position, position + rows - 1);
> bool success = parentNode->insertChildren(position, rows, m_rootNode->columnCount());
> endInsertRows();
>
> return success;
> }
>
> bool TreeModelAdaptor::removeRows(int position, int rows, const QModelIndex &parent)
> {
> TreeNode *parentNode = nodeFromIndex(parent);
>
> beginRemoveRows(parent, position, position + rows - 1);
> bool success = parentNode->removeChildren(position, rows);
> endRemoveRows();
>
> return success;
> }
>
> TreeNode* TreeModelAdaptor::nodeFromIndex(const QModelIndex &index) const
> {
> if (index.isValid())
> {
> TreeNode *item = static_cast<TreeNode*>(index.internalPointer());
> if (item)
> return item;
> }
> return m_rootNode;
> }
>
>
> This email is confidential. It may also be privileged or otherwise protected by work product immunity or other legal rules. If you are not the intended recipient please notify the sender. Please delete the message from all places in your computer where it is stored. You should not copy the email or use it for any purpose or disclose its contents to any other person.To do so may be unlawful. Email is an informal means of communicating and may be subject to data corruption accidentally or deliberately. For this reason it is inappropriate to rely on advice contained in an email without obtaining written confirmation of it first.
>
> FXhome Limited is a limited company registered in England and Wales. Registered number: 04172812. Registered office: The Henderson Business Centre, Ivy Road, Norwich, Norfolk, NR5 8BF, U.K.
>
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
More information about the Qt-interest-old
mailing list