我用Qt 4.x编写了一个用C ++编写的小文件传输应用程序...它登录到服务器,向用户显示服务器上可用的文件列表,并允许用户上传或下载文件
这一切都很好;您甚至可以从桌面(或从打开的文件夹)拖入文件,当您将文件图标放入server-files-list-view时,删除的文件将上传到服务器。
现在我也请求相反的操作...我的用户希望能够将文件从server-files-list-view拖到桌面上,或者打开到打开的文件夹窗口,并将该文件下载到该位置。
这似乎是一个合理的要求,但我不知道如何实现它。有没有办法让Qt应用程序找到与“drop event”发生位置相对应的目录,当图标被放到桌面上或打开文件夹窗口时?理想情况下,这将是一个基于Qt的平台中立机制,但如果不存在,那么MacOS / X和Windows(XP或更高版本)的平台特定机制就足够了。
有什么想法吗?
答案 0 :(得分: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示例显示了这一原则。
您可能还必须覆盖hasFormat
和formats
以提供相应的类型,application/octet-stream
可能是可能让您玩得最多的类型,您可能需要阅读关于windows如何使用mime类型专门处理拖放。
我不知道你将如何提供保存文件的文件名,但你可能不得不进入窗口方面。查看QWindowsMime
的来源也可能有所帮助。我可能会采用多步骤流程来获取文件名text/uri-list
数据的请求,然后application/octet-stream
获取数据请求。
希望这有帮助
答案 1 :(得分:3)
我认为你是以错误的方式解决这个问题。
你不关心掉落的地方,你只知道掉落了。在DropEvent中,将文件下载到临时位置,然后将mime数据设置为下载的内容。当然这可能最终得到硬盘的第二个副本,它将从一开始就是跨平台。您可以使用特定于平台的呼叫对其进行优化。
看一下Dropsite example,了解mime数据如何与其他来源合作......
编辑:
如果你不编写shell扩展(至少对于windows),看起来像双重复制方法是标准。 Filezilla和7zip都这样做,它们返回一个带有临时位置的“text / uri-list”mime类型。这种方式,资源管理器将数据从临时位置复制到真实位置。您的应用程序也可以这样做,创建一个没有数据的临时文件(或只是名称)。使用delayed encoding example,在drop上创建数据。这整个操作非常具有平台特性。在Linux(运行KDE)上,我可以根据mime类型进行拖放。看起来窗口并不灵活。
答案 2 :(得分:2)
您只需实施the drag part即可。您不需要知道丢弃发生的位置,因为接收它的应用程序将处理它并决定存储文件的位置。
你创建了一个QMimeData,不确定哪种类型,但是从我看到的here和here,也许是“application / octet-stream”,你的文件作为QByteArray中的数据或带文件网址的“text / uri-list”。
你创建一个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);
}
}
}
对不起,这是非常不完整的,我希望它有所帮助。