Qt QTreeView:仅允许放弃现有项目

时间:2011-08-04 13:15:46

标签: c++ qt qtreeview

我有一个从QTreeView继承的自定义模型。我已启用拖放功能,并且当前可以将项目拖放到树上。但是,您当前可以放入现有项目或项目之间。我想限制这一点,以便您只能删除现有项目。

我已将DragDropOverwriteMode设置为true(实际上这是QTreeView的默认值)。但是,这并不能阻止您在项目之间删除 - 这只意味着您也可以放弃现有项目。

我知道我可以通过检查行和列是否有效来忽略dropMimeData中的“插入”删除(删除现有项目的行和列设置为-1,父设置为当前项目),我这样做。但是,我不希望得到这些滴剂。 IE浏览器。我希望它能让你总是掉到上面的项目或下面的项目,从不在项目之间。

有什么想法吗?

感谢您的任何建议, 贾尔斯

3 个答案:

答案 0 :(得分:3)

您需要通过在自定义视图中重新实现dragEnterEvent方法来捕获拖动输入事件。 Qt文档中的示例是:

void Window::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/plain"))
        event->acceptProposedAction();
}

在您的情况下,您可能需要将事件中的x和y位置与最近项目的x和y位置或类似物进行比较,并根据该信息拒绝或接受建议的操作。

来自QAbstractItemModel::dropMimeData文档:

  

视图有责任为应插入数据的位置提供合适的位置。

我已经解释为,如果不是基础模型支持的视图,视图应该拒绝掉落,例如你的。

答案 1 :(得分:2)

从Qt 5.4开始(我认为即使在Qt 4.8中也是如此),将DragDropOverwriteMode设置为true正确会导致拖动仅在现有的情况下可以删除项目并防止出现“上方/下方项目”放置目标。

此外,与问题所声称的不同,DragDropOverwriteMode默认设置为false QTreeView(我没有检查,也许是较新的Qt版本),所以它需要手动设置为true

然而,能够计算物品可以放置的位置仍然是有用的。例如,在QTreeView中,不能在项目的左边缘放置拖动的东西,即下面的红色区域:

QTreeView invalid drop areas

如果在无效的红色区域中删除了某些内容,则会在dropMimeData参数设置为parent的情况下调用NULL。因此,ignore提前dragMoveEvent显示“你不能放在这里”光标给用户会很有用所以他们知道他们不能放弃那里。在拖动时Qt没有实现在无效区域上更改鼠标光标(从Qt 5.4开始),但我们可以这样做:

bool SubclassedTreeView::dropResultsInValidIndex(const QPoint& pos)
{
    QTreeWidgetItem* item = itemAt(pos);
    if (item == NULL || !indexFromItem(item).isValid())
        return false;
    return visualRect(indexFromItem(item)).adjusted(-1, -1, 1, 1).contains(pos, false);
}

virtual void SubclassedTreeView::dragMoveEvent(QDragMoveEvent* event)
{
    QTreeWidget::dragMoveEvent(event);
    if (!event->isAccepted())
        return;

    if (dropResultsInValidIndex(event->pos()))
        event->accept();
    else
        event->ignore(); //Show 'forbidden' cursor.
}

virtual bool SubclassedTreeView::dropMimeData(QTreeWidgetItem* parent, int index, const QMimeData* data, Qt::DropAction action)
{
    Q_UNUSED(index);
    //Modify the following action and data format checks to suit your needs:
    if (parent == NULL || action != Qt::CopyAction || !data->hasFormat("my/preferred-type"))
        return false;

    QModelIndex modelIndex = indexFromItem(parent);
    //modelIndex is where the data is dropped onto. Implement your custom drop action here...

    return true;
}

以上代码包含从visualRect….adjusted(-1, -1, 1, 1)来源窃取的一小部分QAbstractItemViewPrivate::position。实际上,当QAbstractItemViewPrivate::positionfalse时,此函数的来源可用于计算项目的覆盖/插入/无效区域。

答案 2 :(得分:0)

我想根据下降指示器(QAbstractItemView::DropIndicatorPosition)的当前位置提出一个解决方案。它的实现非常简单,但不幸的是,要求显示放置指示器。但是,在某些情况下这可能是可以接受的。

TreeView::TreeView(QWidget* parent) : QTreeView(parent)
{
    setDropIndicatorShown(true);
}

void TreeView::dragMoveEvent(QDragMoveEvent* event)
{
    QTreeView::dragMoveEvent(event);

    if (dropIndicatorPosition() != QTreeView::OnItem)
        event->setDropAction(Qt::IgnoreAction);
}