Qt源码之魔改QFileDialog之路-1

发布于 17 天前  123 次阅读


前言

之前着急发Linux社区版本的WPS,所以这里都没有好好的去更改打开本地文件对话框那里的逻辑。由于这里的代码是从其它平台迁移过来的,所以这里的逻辑就没有动。对于用户交互来讲可以说是非常恶心心了。因为我们是做产品的,产品驱动技术。这次呢,前前后后大概花了两周的时间终于把这个产品稳定下来了。里边碰到了一些技术要点与难点。这里简单的总结下。

图1. 原来没有

自己造轮子

实际上这是我的第一个方案,一开始想得太简单,用了个递归的方式去读取QFileInfo的信息,发现栈爆了,然后用QFileSystQFileemModel来读取当前文件夹的信息。总结下就是使用QFileSystQFileemModel +QFileSystemWatcher + QAbstractItemDelegate的方式去做,做了一个星期,完成了七八成,但是发现细节真的太多了,再给我两个星期我可能都做不完,于是放弃这个方案。突然想起来Qt还有个自带的QFileDialog。于是才开始我的第二个方案。

使用QFileDialog类

这个方案我一开始连想都没有想,只是想尝试下看看能不能改造下,发现最终经过了一个星期的改造+适配也是把这个功能完成了。然后加到WPS中了。下边开始讲我在开发中遇到的一些技术要点。

QFileDialog简单介绍

QFileDialog实现基本上是我自己实现的复杂版本,基本要点也是QFileSystemModel类来显示当前的目录信息,使用QFileInfoGatherer 线程类专门监视目录的变化。QFileInfoGatherer线程类基本实现核心也是QFileSystemWatcher,使用了 条件变量 + 锁来做同步。具体的实现还是相当多的, 大家有兴趣可以去阅读下Qt的源码。

如何改造QFileDialog类

改造利器

与其说是如何改造QFileDialog类,不如说是如何改造Qt官方提供的控件,这种方式有一个缺点,就是严重依赖Qt官方源码(ps,有兴趣的可以把这个类的代码提取出来,我去fork,逃))。像WPS自己维护的Qt分支,这个方式我是可以接受的,因为源码就在我这里,哈哈。跑偏了,基本上这样改造是没有多大问题的,官方现在对于QWidget这套代码改动实际上是很少的。现在说一下改造QFileDialog的利器
- findChild()
- findChildren()
- metaObject()->className() (实际上这个基本没用到,了解下也是很好的)

改造原理

todo findchild与findchildren的文章。
findChild<QLineEdit*>("fileNameEdit");

  • 设置QFileDialog的setOption
  • 使用fildChild通过控件名 或者通过findChildren 找到 需要隐藏的左边列表,然后setVisible(false);

这样最关键的问题解决了,可以把这个东西设置成无边框然后嵌入到右边的控件中。然后在对话框中左边加上几个侧边栏,然后主要问题就解决了。

改造细节,其它的相关细节,比如过滤器相关的属性设置QFileDialog都有相关的接口去设置(这个自己去阅读API文档去),唯一一个需要我去解决的就是保存时要将后缀名取出来,然后用到了QtFileDialog中的正则表达式,我已经提取出来了。

TODO

以为这就完了?图样图内务。还有移动介质呢?!


公交车司机终于在众人的指责中将座位让给了老太太