【问题标题】:Qt How to Prevent dropping item FROM application TO Windows File ExplorerQt 如何防止将项目从应用程序拖放到 Windows 文件资源管理器
【发布时间】:2014-02-13 02:04:21
【问题描述】:

我正在寻找一种干净且跨平台的方法来防止将项目从 Qt 应用程序拖放到 Windows 文件资源管理器(或其他操作系统等效项)

下图显示了所需的行为:

我没有运气在网上找到示例或一起破解解决方法,但它似乎是一个足够常见的用例,会有一个设计和实施良好的解决方案。

我尝试过但没有工作:

  • 检测拖拽并杀死它:

    1. 检测QDragEnterEvent、QDragMoveEvent、QDragLeaveEvent
    2. 将事件的 answerRect() 或 pos() 与几何 用于检测拖动是否离开应用程序的 Window 或 Widget

    这很 hacky(而且暂时不工作),我希望你能指出我更优雅的解决方案。

(更新 - 尝试更改 mimeType,但 Windows 文件资源管理器仍然接受删除)

  • 将 MIME 类型更改为自定义类型:

    1. Pre:上图中的“带拖放功能的小部件”是 QTreeViewQFileSystemModel 模型
    2. 子类化QFileSystemModel 并覆盖mimeTypes() 函数,如下面的代码
    3. qDebug() 输出中,看起来mimeType 设置正确,但Windows 文件资源管理器仍然接受drop:/
QStringList MyFileSystemModel::mimeTypes() const  
{  
    QStringList customMimeTypes;  
    customMimeTypes << QString("UnicornsAndRainbows/uri-list");  
    qDebug() << "customMimeTypes: " << customMimeTypes;
    return customMimeTypes;  
}  

如果有机会请告诉我。

谢谢! :)

【问题讨论】:

  • 只需将 mime 类型填充到任何自定义字符串。
  • 在检查dropEvent 上的mimeType 之后,我发现我的上述实现没有正确设置mimeType。我目前有一些来自4.8 Drag and Drop Documentation 的用于我的用例的代码,一旦我清理它就会发布我的代码。谢谢德米特里! :)

标签: c++ qt drag-and-drop


【解决方案1】:

Dmitry Sazonov 给出了正确答案。我将在下面解释我是如何实现它的。德米特里,如果您想要信任,请将其发布为答案而不是评论,以便我接受它作为答案。

根据 Dmitry 的建议,我在问题更新中做错的是覆盖 QFileSystemModel::mimeTypes(),而事实上,我不得不修改 QTreeView::mouseMoveEvent()QTreeView::dropEvent()

//---------------------------------------------------------
void MyTreeView::mouseMoveEvent( QMouseEvent *event )
{
    if( !(event->buttons() & Qt::LeftButton) )
    {
        return; // we only care about left mouse drags at the moment
    }

    if( (event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance() )
    {
        return; // a buffer when calculating waht qualifies as a "drag event"
    }

    QDrag *drag = new QDrag( this );
    QMimeData *mimeData = new QMimeData();
    QByteArray data;
    const QStringList selectedPaths = this->getSelectedPaths(); // custom helper method

    foreach( QString path, selectedPaths )
    {
        data.append( path ).append( ";" ); // using ';' as path deliminator
    }
    data.chop( 1 );

    //--- this sets the custom MIME Type filter 
    mimeData->setData( CUSTOM_MIMETYPE_STRING, data );

    drag->setMimeData( mimeData );

    Qt::DropAction dropAction = drag->exec( Qt::CopyAction );
}


//---------------------------------------------------------
void MyTreeView::dropEvent( QDropEvent *event )
{
    // ...

    QList<QByteArray> paths;

    //--- this filters based on our custom MIME Type
    paths = event->mimeData()->data( CUSTOM_MIMETYPE_STRING ).split(';');

    foreach( QByteArray path, paths )
    {
        // do something with the file paths
    }
}

【讨论】:

  • 还请注意,不应使用愚蠢的“Widget Container Moat”,因为正确的解决方案是使用自定义 MIME 类型。
  • 我试过了,但现在我不能在我自己的应用程序中删除数据,我必须在任何地方注册这个自定义 mimetype 吗?
猜你喜欢
  • 2020-10-29
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 2011-02-22
  • 2014-12-26
相关资源
最近更新 更多