gpt4 book ai didi

c++ - Qt信号转发;继承QAbstractProxyModel

转载 作者:太空宇宙 更新时间:2023-11-04 11:52:28 47 4
gpt4 key购买 nike

文档似乎是关于这个的,我在 StackOverflow 和其他地方看到了一堆模棱两可的示例代码,所以......

如果我有一个类 A 实现了一个 QAbstractProxyModel 和一个类 B 实现了一个 QAbstractItemModel 并且我在 A 的实例上调用 setSourceModel(b) 方法,其中 bB 的实例,自动处理转发更新信号,例如 modelResetrowsInserted 等?还是我必须手动连接所有这些?

最佳答案

你是对的,文档对此毫无帮助。查看 QAbstractProxyModel 的源代码并将其与 Qt 5.12 中的 QSortFilterProxyModel 进行比较,得出 QAbstractProxyModel 决不会处理 dataChanged 信号的转发!你必须自己做!最好选择更复杂的模型,例如 QSortFilterProxyModel 或 QIdentityProxyModel,它们会为您执行此转发。但如果你真的无法绕过它,那么它可能看起来像这样:

/**
* Proxy model which only returns one data row of the underlying QAbstractItemModel
* except for the first column. Can be used to separate a model for QTreeView into
* the tree column and the data columns. This proxy returns the data columns.
* Can't use QSortFilterProxyModel because it does not allow for only showing one
* row if its parent is filtered out.
*/
class SingleRowProxy :
public QAbstractProxyModel
{
Q_OBJECT;

using BaseType = QAbstractProxyModel;

static constexpr auto FIRST_DATA_COLUMN = 1;

public:
SingleRowProxy( QAbstractItemModel* sourceModel,
int row,
const QModelIndex& parentIndex,
QObject* parentObject = nullptr ) :
BaseType( parentObject ),
m_sourceRow( row ),
m_sourceParent( parentIndex )
{
Q_ASSERT( sourceModel != nullptr );
setSourceModel( sourceModel );

}

void setSourceModel( QAbstractItemModel *newSourceModel ) override
{
if ( newSourceModel == sourceModel() ) {
return;
}

beginResetModel();

disconnect( newSourceModel, nullptr, this, nullptr );

BaseType::setSourceModel( newSourceModel );

connect( newSourceModel, &QAbstractItemModel::dataChanged,
this, &SingleRowProxy::sourceDataChanged );
connect( newSourceModel, &QAbstractItemModel::modelAboutToBeReset,
this, [this] () { beginResetModel(); } );
connect( newSourceModel, &QAbstractItemModel::modelReset,
this, [this] () { endResetModel(); } );
}

QModelIndex
mapFromSource( const QModelIndex& sourceIndex ) const override
{
if ( !sourceIndex.isValid() || ( sourceIndex.column() < FIRST_DATA_COLUMN ) ) {
return {};
}
return index( 0, sourceIndex.column() - FIRST_DATA_COLUMN, QModelIndex() );
}

QModelIndex
mapToSource( const QModelIndex& proxyIndex ) const override
{
if ( !proxyIndex.isValid() ) {
return {};
}
return sourceModel()->index( m_sourceRow,
proxyIndex.column() + FIRST_DATA_COLUMN,
m_sourceParent );
}

QVariant
data( const QModelIndex& index,
int role ) const override
{
return sourceModel()->data( mapToSource( index ), role );
}

int
rowCount( [[maybe_unused]] const QModelIndex& parent = QModelIndex() ) const override
{
return sourceModel()->hasIndex( m_sourceRow, FIRST_DATA_COLUMN, m_sourceParent ) ? 1 : 0;
}

int
columnCount( [[maybe_unused]] const QModelIndex& parent = QModelIndex() ) const override
{
return sourceModel()->columnCount( sourceModel()->index( m_sourceRow, 0, m_sourceParent ) );
}

QModelIndex
index( int row,
int column,
const QModelIndex& parent ) const override
{
if ( !hasIndex( row, column, parent ) ) {
return {};
}

return createIndex( row, column );
}

QModelIndex
parent( [[maybe_unused]] const QModelIndex& child ) const override
{
return {};
}

private slots:
/**
* QSortFilterProxyModel does it for us but QAbstractProxyModel does not!
* So we have to map the source indices and reemit the dataChanged signal. */
void
sourceDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
{
if ( !topLeft.isValid() ||
!bottomRight.isValid() ||
( topLeft.parent() != bottomRight.parent() ) )
{
return;
}

const auto& parent = topLeft.parent();

int minRow = std::numeric_limits<int>::max();
int maxRow = std::numeric_limits<int>::lowest();
int minCol = std::numeric_limits<int>::max();
int maxCol = std::numeric_limits<int>::lowest();
bool foundValidIndex = false;

for ( int sourceRow = topLeft.row(); sourceRow <= bottomRight.row(); ++sourceRow ) {
for ( int sourceColumn = topLeft.column(); sourceColumn <= bottomRight.column(); ++sourceColumn ) {
const auto index = mapFromSource( sourceModel()->index( sourceRow, sourceColumn, topLeft.parent() ) );
if ( !index.isValid() ) {
continue;
}

minRow = std::min( minRow, index.row() );
maxRow = std::max( maxRow, index.row() );
minCol = std::min( minCol, index.column() );
maxCol = std::max( maxCol, index.column() );
foundValidIndex = true;
}
}

if ( foundValidIndex ) {
emit dataChanged( index( minRow, minCol, parent ),
index( maxRow, maxCol, parent ),
roles );
}
}

private:
const int m_sourceRow;
const QModelIndex m_sourceParent;
};

你必须做 index mapping因为代理索引与源模型索引不同!

请注意,此示例只是非常初级的,可能不适用于任意映射。

请注意,对于完整的代理模型,您必须映射和转发所有信号。 QSortFilterProxyModel 在 setSourceModel 中重新连接这些信号:

  • 数据已更改
  • headerDataChanged
  • rowsAboutToBeInserted
  • 已插入行
  • 关于要插入的列
  • 已插入列
  • rowsAboutToBeRemoved
  • 删除的行数
  • 关于删除的列
  • 删除的列
  • rowsAboutToBeMoved
  • 移动的行数
  • 列AboutToBeMoved
  • columnsMoved
  • layoutAboutToBeChanged
  • 布局改变
  • modelAboutToBeReset
  • 模型重置

关于c++ - Qt信号转发;继承QAbstractProxyModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17562181/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com