C++ Qt5:使用QSortFilterProxyModel时拖放
我有一个模型,它是从C++ Qt5:使用QSortFilterProxyModel时拖放,c++,qt,c++11,qt5,qsortfilterproxymodel,C++,Qt,C++11,Qt5,Qsortfilterproxymodel,我有一个模型,它是从QAbstractListModel子类划分的,它有不同的列表视图,这些视图使用子类QSortFilterProxyModel对每个视图进行过滤。当用户单击排序按钮时,可以对视图中的数据进行排序 我在QSortFilterProxyModel中实现了拖放,以在将数据拖放到新的Listview中时更改数据的状态。这很好,但是,手动排序listview中的项目会导致显示相同数据的所有其他listview也被排序,这不是我想要的 例如,视图1显示所有参与者,视图2显示活动的参与者。
QAbstractListModel
子类划分的,它有不同的列表视图,这些视图使用子类QSortFilterProxyModel对每个视图进行过滤。当用户单击排序按钮时,可以对视图中的数据进行排序
我在QSortFilterProxyModel中实现了拖放,以在将数据拖放到新的Listview中时更改数据的状态。这很好,但是,手动排序listview中的项目会导致显示相同数据的所有其他listview也被排序,这不是我想要的
例如,视图1显示所有参与者,视图2显示活动的参与者。当从视图1拖动到视图2时,参与者变为活动状态。如果我手动对参与者进行排序,那么活动参与者的索引也会被排序。但是,如果我使用proxyModel->sort()
方法自动对它们进行排序,则不会发生这种情况
如何在不更改源模型中的索引的情况下手动重新排列代理模型中的数据
示例代码:
MySortFilterProxyModel::MySortFilterProxyModel(bool active, QObject *parent ) :
QSortFilterProxyModel( parent ),
m_filter( "" ),
m_active(active)
{
setDynamicSortFilter( false );
}
void MySortFilterProxyModel::setFilter( QString filter )
{
m_filter = filter;
invalidateFilter();
}
Qt::ItemFlags MySortFilterProxyModel::flags( const QModelIndex &index ) const
{
if( index.isValid() )
{
return ( QSortFilterProxyModel::flags( index ) | Qt::ItemIsDragEnabled | Qt::ItemIsEditable );
}
return Qt::ItemIsDropEnabled | QSortFilterProxyModel::flags( index );
}
bool MySortFilterProxyModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
{
if( !data->hasFormat( dataModel::dataMimeType() ) )
{
return false;
}
if( action == Qt::IgnoreAction )
{
return true;
}
if( column > 0 )
{
return false;
}
QByteArray encodeData = data->data(dataModel::dataMimeType());
QDataStream stream( &encodeData, QIODevice::ReadOnly );
while( !stream.atEnd() )
{
DataRecord *dr = new DataRecord();
stream >> dr;
dr->setActive( m_active );
// AddData method in the dataModel removes duplicate rows and inserts the data into the correct row.
qobject_cast< DataModel * >( sourceModel() )->addData( fdr, parent.row() );
}
return true;
}
在数据模型中,我还实现了以下方法:
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
bool setData( const QModelIndex & index, const QVariant & value, int role=Qt::EditRole );
bool removeRows( int row, int count, const QModelIndex &parent ) override;
QMimeData *mimeData( const QModelIndexList &indexes ) const override;
QStringList mimeTypes() const override;
int rowCount( const QModelIndex &parent ) const override;
Qt::DropActions supportedDropActions() const override;
不要修改DataModel
QSortFilterProxyModel
的要点是,您可以完全独立于基础数据的任何其他视图提供新的排序。让该视图移动基础行会打断该视图
相反,您应该编写一个代理,该代理提供对排序的手动覆盖,记录每行的位置。这可以使用
QSortFilterProxyModel
作为它的源,它反过来又从DataModel
中源。你能显示DataModel::addData
吗?是的,我把它添加到了问题中。没有mapToSource()
父项,你不能传递parent.row()
,并确保它是有效的。好的,但我仍然只是更新sourceModel的索引,而不仅仅是代理模型。我想知道我是否应该在ProxyModel中实现mimeData方法,并以某种方式跟踪代理过滤的项,但这对我来说并不明显。不幸的是,如果不看到模型实现,很难看到出了什么问题。QabstracteModel子类化是一个雷区,我想对数据进行手动和自动排序,例如,当单击调用“proxyModel->sort()”的按钮时,按名称按字母顺序自动排序数据。这就是为什么'setDynamicSortFilter(false)'设置了,并且已经为字母排序实现了“lessThan”。然后您需要另一个代理层:DataModel
->QSortFilterProxyModel
->DragDropReorderProxyModel
其中DragDropReorderProxyModel派生QAbstractProxyModel并实现mapFromSource/maptosource这是一个好主意,非常感谢。我不认为你可以分层代理。我试试看。
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
bool setData( const QModelIndex & index, const QVariant & value, int role=Qt::EditRole );
bool removeRows( int row, int count, const QModelIndex &parent ) override;
QMimeData *mimeData( const QModelIndexList &indexes ) const override;
QStringList mimeTypes() const override;
int rowCount( const QModelIndex &parent ) const override;
Qt::DropActions supportedDropActions() const override;