0x01 QT中的拖拽支持
QT为我们提供了一整套的框架实现拖拽支持,可以为用户提供直观的跨应用或同应用内实现**“信息转移”。主要有将其拆分成了拖拽(Drag)与放置(Drop)**这两部分。
拖拽本质上是将信息转为MIME
在Widget
间转移
由于本文主要实现的是拖拽文件进入程序打开文件,因此主要关注后面的部分,其关键的方法有:
dragEnterEvent
dropEvent
0x02 放置(Drop)支持
为了使QWidget
支持该特性,首先需要调用setAcceptDrops(true)
来为该QWidget
开启支持。同时还需要实现dragEnterEvent()
与dropEvent()
两个**事件处理器(Event Handler)**来实现其业务功能。
dragEnterEvent
该方法主要是用于告知QT当前QWidget
支持接收什么类型的数据,如下代码将告知QT的Drag&Drop系统当前QWidget
只能处理纯文本内容:
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("text/plain"))
event->acceptProposedAction();
}
实际上,QMimeData
已经有一些很方便的方法来对应这些类型:
Tester | Getter | Setter | MIME Types |
---|---|---|---|
hasText() | text() | setText() | text/plain |
hasHtml() | html() | setHtml() | text/html |
hasUrls() | urls() | setUrls() | text/uri-list |
如果在该方法中,没有调用event
的acceptProposedAction()
方法,则拖拽进入窗口的内容为显示为禁止符号以提示用户该内容不支持,且不会继续进入dropEvent
处理该事件。
dropEvent
该方法主要真正实现进入数据的解包,并按所需业务逻辑的需要进行处理,在这里主要对MIME进行真正的处理。
其携带的MIME信息与上一步的类同,就不再展开了。
0x03 实现拖拽打开文件
文件拖拽进入窗口后,实际上是以url
的形式存在的,即传入的是文件路径。
因此我们的处理过程将分为3步:
dragEnterEvent
判断传入的Event
是否包含Url
dropEvent
将urls
分解,并过滤不合规的url
。- 将剩余的
urls
传递给打开文件的部分
下面看下具体实现:
/* dragEnterEvent 过滤无用Event */
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasUrls())
event->acceptProposedAction();
}
/* dropEvent 过滤无用urls,并将有效部分交给文件读取方式加载 */
void MainWindow::dropEvent(QDropEvent *event)
{
QList<QUrl> urls = event->mimeData()->urls();
QStringList files;
QString suffixs = "bmp jpg jif jpeg png gif webp psd tif tiff mp4 avi mkv mpg wmv webm rm rmvb mov flv 3gp ts pdf";
for( QUrl url : urls ){
QFileInfo file(url.toLocalFile()); //toLocalFile可以获取文件路径,而非QUrl的file://开头的路径
if( file.isFile() && suffixs.contains(file.suffix())) //过滤掉目录和不支持的后缀,如果要支持目录,则要自己遍历每一个目录。
files.append(file.filePath());
}
if(!files.isEmpty())
MediaFileModelItemManager::getInstance()->requestReadFilesAsync(files); //将文件交给文件打开逻辑进行后续的处理
}