我有一个QAbstractItemModel
派生类附加到QTreeView
。
模型实现2个顶级行,其中一个行有3个子行。仅显示前2个子行。如果我添加一个“虚拟”顶级行,则显示所有内容。
我使用qDebug()
来打印QTreeView
调用model::data()
的次数以及索引(仅打印Qt::DisplayRole
个案例)并看到它实际上被称为2 {子行的次数而不是3次。
当然,首先怀疑我的model::rowCount()
是不正确的,并使QTreeView
“认为”只有2个子行。所以这里是qDebug()
打印:
rowCount returning 3 for parent 0xbc6f70
…….
Qt::DisplayRole for row 0 ,column 0 pointer 0xbc6fc0 parent= 0xbc6f70
Qt::DisplayRole for row 1 ,column 0 pointer 0xbc7068 parent= 0xbc6f70
其中0xbc6f70是:
parent.internalPointer()
中model::rowCount(const QModelIndex &parent)
在index.parent().internalPointer()
model::data(const QModelIndex &index, int role)
那么,如果model::data()
为model::rowCount()
的索引返回3,为什么要为第0行和第1行调用internalPointer() 0xbc6f70
而不为第2行调用?
以下是代码:
int Model_Tree::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
{
// This is 1st level
qDebug() << "rowCount returning m_RowCount" << m_RowCount << "for !parent.isValid()" << parent.internalPointer() << "row" << parent.row() << "column" << parent.column();
return m_RowCount;
}
int column = parent.column();
if(0 != column)
{
qDebug() << "rowCount returning 0 for parent 0 != column (" << column << ")";
return 0; // only item at 0th column can have children
}
const TreeItem* pTreeItem = (const TreeItem*)parent.internalPointer();
if (0 == pTreeItem)
{
qDebug() << "rowCount returning 0 for parent 0==pTreeItem" << pTreeItem;
return 0;
}
qDebug() << "rowCount returning " << pTreeItem->m_Children.size() << "for parent " << pTreeItem << "type:" << pTreeItem->m_type;
return pTreeItem->m_Children.size();
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* p = index.internalPointer();
int column = index.column();
int row = index.row();
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << p << "parent=" << index.parent().internalPointer();
// .... the rest of Model_Tree::data implementation
}
这里有一些qDebug()输出:
rowCount returning 3 for parent **0x122ee138** type: 0
....
Qt::DisplayRole for row 0 ,column 0 pointer 0x122ee168 parent= **0x122ee138**
Qt::DisplayRole for row 1 ,column 0 pointer 0x122ee198 parent= **0x122ee138**
note 0x122ee138 - 这是包含3个孩子的父节点的“internalPointer”值
这里是index()和parent()实现:
QModelIndex Model_Tree::index(int row, int column, const QModelIndex &parent) const
{
void* p = 0;
if (!parent.isValid())
{
// This is 1st level
// we use our whole record
if (row < m_RowCount)
{
const TreeItem& treeItem = *(m_pRootItem->m_Children.at(row));
const LogRecord* pRecord = treeItem.m_pRecord;
const LogRecord& record = *pRecord;
if (column == 0)
{
p = (void*)&treeItem; // because createIndex() wants void* a 3rd parameter
}
else
{
const QList<QVariant>& fieldList = record.fieldList;
if (column <= fieldList.size())
{
const QVariant* pField = &(fieldList[column - 1]); // -1 Because we have extra column at left side
if ( (QMetaType::Type)(pField->type()) == QMetaType::QString )
{
//const QString *pString = static_cast<const QString*>(pField->data());
p = const_cast<void*>(pField->data());
}
if ( (QMetaType::Type)(pField->type()) == QMetaType::QStringList )
{
const QStringList *pStringList = static_cast<const QStringList*>(pField->data());
//const QString *pString = &(pStringList->at(0)) ;
p = const_cast<void*>( static_cast<const void*>( &(pStringList->at(0)) ) );
}
}
}
}
//qDebug() << "Creating index: " << row << ", " << column << ", " << p;
return createIndex(row, column, p);
}
if (0 != column)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 != column)";
return createIndex(row, column, (void*)0);
}
p = parent.internalPointer();
const TreeItem* pTreeItem = (const TreeItem*)p;
if (0 == pTreeItem)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 == pTreeItem)";
return createIndex(row, column, (void*)0);
}
if (row < pTreeItem->m_Children.size())
{
const TreeItem* pTreeSubItem = pTreeItem->m_Children.at(row).data();
//qDebug() << "Creating subline index: " << row << ", " << column << ", " << (void*)pTreeSubItem << "parent: " << pTreeItem;
return createIndex(row, column, (void*)pTreeSubItem);
}
//qDebug() << "Creating index: " << row << ", " << column << ", 0";
return createIndex(row, column, (void*)0);
}
QModelIndex Model_Tree::parent(const QModelIndex &index) const
{
if (!index.isValid())
{
QModelIndex qi;
qDebug() << "Creating INVACHILD PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pChildItem = static_cast<const TreeItem*>(index.internalPointer());
if (0 == pChildItem)
{
QModelIndex qi;
qDebug() << "Creating NOTREEITEM PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pParentItem = pChildItem->m_pParent;
if (0 == pParentItem)
{
QModelIndex qi;
qDebug() << "Creating NOPARENT PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
qDebug() << "Creating PARENT index: " << pChildItem->m_RecordNumber << ", " << 0 << ", " << pParentItem;
return createIndex(pParentItem->m_RecordNumber, 0, (void*)pParentItem);
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* pInternal = index.internalPointer();
int column = index.column();
int row = index.row();
if (0 == column)
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << pInternal << "parent=" << index.parent().internalPointer();
if (0 == pInternal)
{
//qDebug() << "DR: internal pointer is 0";
return QVariant();
}
if (0 == column)
{
const TreeItem* pTreeItem = static_cast<const TreeItem*>(pInternal);
QString displayString;
QTextStream(&displayString) << pTreeItem->m_LogLineNumber;
if (pTreeItem->m_type == TreeItem::Subline)
{
QTextStream(&displayString) << " (" << row << "-th sub-line)"
<< " " << (*(pTreeItem->m_pSubline));
}
if (pTreeItem->m_type == TreeItem::Record)
{
if (pTreeItem->m_Children.size() > 0)
{
QTextStream(&displayString) << " (" << rowCount(index)/*pTreeItem->m_Children.size()*/ << " sub-lines)";
}
}
return displayString;
}
// for columns other than 0 index contains QString* as internal pointer
const QString* pText = static_cast<const QString*>(pInternal);
return *pText;
}
return QVariant();
}
答案 0 :(得分:0)
感谢Marek试图帮助我!
问题出在我的QSortFilterProxyModel派生类中,没有考虑子项)))