c++ - Qt5:使用 QSortFilterProxyModel 时拖放

标签 c++ qt c++11 qt5 qsortfilterproxymodel

我有一个从 QAbstractListModel 子分类的模型具有不同的 ListView ,这些 View 使用子类 QSortFilterProxyModel 为每个 View 进行过滤。当用户单击排序按钮时,可以对 View 中的数据进行排序。

我在 QSortFilterProxyModel 中实现了拖放,以在将数据放入新的 Listview 时更改数据的状态。这工作正常,但是,手动对 ListView 中的项目进行排序会导致所有其他显示相同数据的 ListView 也进行排序,这不是我想要的。

例如, View 1 显示所有参与者, View 2 显示事件的参与者。从 View 1 拖动到 View 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;
}

编辑 addData() 可能有更好的方法来做到这一点:
void DataModel::addData( DataRecord *dr, int row )
{
   int i =0;
   for( auto const& itr : m_dataRecords )
   {
       if( itr->getUniqueID() == dr->getUniqueID() )
       {
          break;
       }
       ++i;
   }
   removeRows( i, 1, QModelIndex() ); 

   beginInsertRows( QModelIndex(), row, row );
   m_dataRecords.insert( row, dr );
   endInsertRows();
  } 

在 DataModel 中,我还实现了以下方法:
 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;

最佳答案

请勿修改 DataModelQSortFilterProxyModel点是您可以完全独立于底层数据的任何其他 View 提供新的排序。让该 View 移动底层行会打破这一点。

相反,您应该编写一个代理,提供手动覆盖排序,记录每行应放置的位置。这可以使用 QSortFilterProxyModel作为其来源,而后者又来自 DataModel

关于c++ - Qt5:使用 QSortFilterProxyModel 时拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45349341/

相关文章:

c++ - Visual Studio 2015 遇到断点

c++ - 通过 std::function 引用仿函数

c++ - std::is_convertible 与 std::function 不一致

Linux,execl(),为什么我丢失应用程序的键盘输入?

qt - QsslSocket : Cannot access peer (client) certificate on other peer (server)

c++ - 在 Qt5 的 QQuickItem 上捕捉 mouseMoveEvent

c++ - 如何在从 boost 库拆分时添加两个值

c++ - 实例化点可以延迟到翻译单元结束吗?

c++ - 用新 vector 中的对应值替换 vector 中的所有奇数值

c++ - 更改字符串中的多个字符 C++