首页 文章

Qt 4.x:如何实现拖放到桌面或文件夹中?

提问于
浏览
18

我用Qt 4.x写了一个用C编写的小文件传输应用程序...它登录到服务器,向用户显示服务器上可用的文件列表,并让用户上传或下载文件 .

这一切都很好;您甚至可以从桌面(或从打开的文件夹)拖入文件,当您将文件图标放入server-files-list-view时,删除的文件将上传到服务器 .

现在我也请求相反的操作...我的用户希望能够将文件从server-files-list-view拖到桌面上,或者拖到打开的文件夹窗口中,然后让它文件下载到该位置 .

这似乎是一个合理的要求,但我不知道如何实现它 . 有没有办法让Qt应用程序找到与“drop event”发生位置相对应的目录,当图标被放到桌面上或打开文件夹窗口时?理想情况下,这将是一个基于Qt的平台中立机制,但如果不存在,那么MacOS / X和Windows(XP或更高版本)的平台特定机制就足够了 .

有任何想法吗?

3 回答

  • 7

    看看 QMimeData 及其文档,它有一个虚函数

    virtual QVariant retrieveData  ( const QString & mimetype, QVariant::Type type ) const
    

    这意味着你拖到外面就可以相应地实现这个功能

    class DeferredMimeData : public QMimeData
    {
      DeferredMimeData(QString downloadFilename) : m_filename(downloadFilename)
    
      virtual QVariant retrieveData (const QString & mimetype, QVariant::Type type) const 
      {
        if (mimetype matches expected && type matches expected)
        {
           perform download with m_filename
        }
      }
    }
    

    delayed encoding示例显示了这一原则 .

    您可能还必须覆盖 hasFormatformats 以提供适当的类型, application/octet-stream 可能是可能让您玩得最多的类型,您可能必须阅读Windows如何使用mime类型专门处理拖放 .

    我不知道你将如何提供保存文件的文件名,但你可能不得不进入windows方面 . 查看 QWindowsMime 的来源也可能有所帮助 . 可能有一个多步骤过程,您将获得文件名 text/uri-list 数据的请求,然后获取数据的 application/octet-stream .

    希望这可以帮助

  • 3

    我认为你会以错误的方式解决这个问题 .

    你不关心掉落的地方,你只知道掉落了 . 在DropEvent中,将文件下载到临时位置,然后将mime数据设置为下载的内容 . 当然这可能最终得到硬盘的第二个副本,它将从一开始就是跨平台 . 您可以使用特定于平台的呼叫对其进行优化 .

    看看Dropsite example,看看mime数据如何从其他来源工作......

    编辑:

    如果您不编写shell扩展(至少对于Windows),看起来双重复制方法是标准 . Filezilla和7zip都这样做,它们返回一个带有临时位置的"text/uri-list" mime类型 . 这种方式,资源管理器将数据从临时位置复制到真实位置 . 您的应用程序也可以这样做,创建一个没有数据的临时文件(或只是名称) . 使用delayed encoding example,在drop上创建数据 . 这整个操作非常具有平台特性 . 在Linux(运行KDE)上,我可以根据mime类型进行拖放 . 看起来窗户不那么灵活 .

  • 2

    你刚刚实现the drag part . 您不需要知道丢弃发生的位置,因为接收它的应用程序将处理它并决定存储文件的位置 .

    你创建一个QMimeData,不知道哪种类型,但是从我看到herehere,也许是"application/octet-stream",你的文件作为QByteArray中的数据或"text/uri-list"与你的文件的URL .

    您创建一个QDrag,并使用其setMimeData()方法和exec()(不确定选择哪个QT :: DropAction) .

    这是一个例子(disclamer:我用颜色而不是文件):

    void DraggedWidget::mousePressEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton)
            start_pos = event->pos();
    }
    
    void DraggedWidget::mouseMoveEvent(QMouseEvent *event)
    {    
        if (event->buttons() & Qt::LeftButton) {
            int distance = (event->pos() - start_pos).manhattanLength();
            if (distance >= QApplication::startDragDistance())
            {
                /* Drag */
                QMimeData *mime_data = new QMimeData;
    
                mime_data->setData( ... );
    
                QDrag *drag = new QDrag(this);
                drag->setMimeData(mime_data);
                drag->exec(Qt::CopyAction);
            }
        }
    }
    

    对不起,这是非常不完整的,我希望它有点帮助 .

相关问题