QListView外部删除不起作用

时间:2016-03-28 19:54:12

标签: qt drag-and-drop qlistview qsortfilterproxymodel

我正在尝试从一个QListView到另一个QListView实现拖放项目(普通/文本)。拖动开始很好(我甚至能够将项目拖放到另一个接受文本丢弃的应用程序),但我的第二个QListView由于某种原因不接受丢弃。 以下是配置列表视图的方式:

ui->lessonsListView->setAcceptDrops(true);
ui->lessonsListView->setDropIndicatorShown(true);
ui->lessonsListView->setDragDropMode(QAbstractItemView::DropOnly);
ui->lessonsListView->setDragDropOverwriteMode(true);

此listView的代理模型实现了下一个方法:

Qt::ItemFlags LessonsProxyModel::flags(const QModelIndex &index) const
{
    qDebug() << __FUNCTION__;
    return Qt::ItemIsDropEnabled | QSortFilterProxyModel::flags(index);
}

Qt::DropActions LessonsProxyModel::supportedDropActions() const
{
    qDebug() << __FUNCTION__;
    return Qt::MoveAction;
}

bool LessonsProxyModel::canDropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    qDebug() << __FUNCTION__;
    Q_UNUSED(action);
    Q_UNUSED(row);
    Q_UNUSED(column);

    if (!data->hasFormat("text/plain") || !parent.isValid())
        return false;

    return true;
}

bool LessonsProxyModel::dropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    qDebug() << __FUNCTION__;
    if (!canDropMimeData(data, action, row, column, parent))
        return false;

    emit dataDropped(data, parent);

    return true;
}

从应用程序输出中,我看到只调用了supportedDropActions()flags()canDropMimeData()dropMimeData()都没有打过电话。我究竟做错了什么? 任何提示将不胜感激。

谢谢!

编辑:

以防万一:下面是listView的源代码,并且启动了这些拖动的模型: listView设置:

ui->abonsListView->setDragEnabled(true);

proxyModel代码:

Qt::ItemFlags AbonsProxyModel::flags(const QModelIndex &index) const
{
    return Qt::ItemIsDragEnabled | QSortFilterProxyModel::flags(index);
}

Qt::DropActions AbonsProxyModel::supportedDragActions() const
{
    qDebug() << __FUNCTION__;
    return Qt::MoveAction;
}

QStringList AbonsProxyModel::mimeTypes() const
{
    qDebug() << __FUNCTION__;
    QStringList types;
    types << "text/plain";
    return types;
}

QMimeData *AbonsProxyModel::mimeData(const QModelIndexList &indexes) const
{
    qDebug() << __FUNCTION__;
    QMimeData *mimeData = new QMimeData();

    foreach (const QModelIndex &index, indexes)
        if (index.isValid())
        {
            mimeData->setText(data(index, AbonsModel::Id).toString());
            qDebug() << __FUNCTION__;
            return mimeData;
        }

    return mimeData;
}

2 个答案:

答案 0 :(得分:2)

我终于找到了答案!当我开始编写此代码时,我从Qt docs Using Drag and Drop with Item Views中复制了一些内容,在本文中,他们只是错过了const说明符来重新实现canDropMimeData()。因此我的canDropMimeData()版本变为非虚拟版本,QListView只调用基类QAbstractProxyModel中的方法。我添加了const - 所有内容都像没有任何子类的魅力一样。

答案 1 :(得分:0)

我对代理模型的经验不多。通过文档,我想我已经大致了解这两个函数是什么。这些函数不会自动调用。你必须打电话给#34;它们来自你的观点。

首先,检查您是否拥有正确的数据是模型的工作。因此,这些是模型中的两个便利功能,可以简化您的工作。这些是特定于模型的函数,而不是泛型函数,因此永远不会为抽象模型定义。

考虑这种情况。从某处将QMimeData对象放入视图中。你怎么知道这个数据是否是正确的类型?是谁的工作来决定数据是否属于正确的类型?

Model-View框架中,View仅绘制作品。它由Model决定如何处理数据,显示什么,什么是可接受的以及什么不是。因此,当View上放置一段数据时,您需要将其发送到Model,以检查已删除的数据是否满足Model的要求。执行此工作的钩子是bool Model::canDropMimeData(...)

如果可以接受,那么数据的处理也需要由Model本身完成。您需要再次将数据发送到Model。这方面的钩子是bool Model::dropMimeData(...)

您如何知道数据是否成功处理?检查返回值!如果数据处理成功,那么您很可能需要更新View

因此,除了上面的代码之外,您必须会覆盖接收dragEnterEvent的{​​{1}},dragMoveEventdropEvent,您可以致电ViewcanDropMimeData(...)

dropMimeData(...)