从烦人的 WPS "打开方式不对"到翻 Qt 源码 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
rapiz
V2EX    Linux

从烦人的 WPS "打开方式不对"到翻 Qt 源码

  rapiz
rapiz1 2021-04-13 21:13:38 +08:00 7210 次点击
这是一个创建于 1695 天前的主题,其中的信息可能已经有所发展或是发生改变。

问题背景和表现

如果你使用 KDE + archlinux,那么很有可能会遇到这个烦人的问题:WPS 打开文件的方式不对。

问题表现为,在 KDE 上试图单击打开 .xls 文件的时候,WPS Writer 会被调用,并且很有可能卡死(因为文件内容不匹配)。如果你尝试给 .xls 设置默认程序,会发现可能 .doc, .docx, .ppt, .pptx 也被影响。并且这类文件均被识别成 x-ole-storage 而非独立的 Presentation, Word, Spreedsheet 类型。

aur 源里有一个叫 wps-office-mime 的包,安装这个包不能解决问题。

这件事困扰了我很久了,非常烦人,一不小心单击打开表格文件,就会调用 WPS Writer 然后卡死。之前启用 WPS 的整合模式可以解决这个问题,但是自从某个更新后整合模式会崩溃。

有一天,我再也忍不了了,下定决心要把这件事调查清楚……

调查和解释

首先解释一个名词,mimetype,简单来说就是“判断一个文件是什么类型,应该用什么程序打开”的规则。

前面提到,很多不同的文档文件( doc, ppt, xls) 都被匹配成 x-ole-storage 了,而一个类型的文件只有一个默认打开程序,因此要关联就都关联到 WPS Writer 上从而导致错误结果。

问题:我的 .xlsx 文件是怎么被识别成 x-ole-storage 文件并打开的?

我打开 KDE 的 File Associations,里面确实有 .ppt, .doc, .xls 的 mimetypes 及其关联的打开程序,看起来非常正常。但是为什么这些规则没有匹配到我的文件上呢?为什么文件没有被正确归类成幻灯片,文档,表格,而是那个不知哪里来的 x-ole-storage 类型?

ArchWiki 有关于 mimetypes 的一些介绍。其中提到系统直接读取的 mimetypes 其实是一种数据库,或者说缓存,是根据安装过的软件包的原始 mimetype 配置文件生成的结果。

原始 mimetype 配置文件储存在:

  • /usr/share/mime/packages

  • ~/.local/share/mime/packages

并且我们可以用 update-mime-database 来根据配置刷新缓存。

好吧,可是这些知识对于解决我的问题并没有帮助。

不过,至少经过在这些目录里搜索,我发现 x-ole-storage 的定义来源于 /usr/share/mime/packages/freedesktop.xml,属于 XDG 标准内容,看来我不应该删除掉它的定义。

看来需要调查 KDE 识别并打开文件的过程了。

根据日常使用 KDE 的经验和猜想,在 Dolphin 里单击一个文件,和使用 xdg-open 命令的效果是完全相同的。经过一些搜索,我发现 xdg-open 依赖 kde-cli-tools 包来打开文件,那么想要调查 KDE 打开文件,自然要去看这个包里都有什么工具了。

找到其源码,看一下目录结构初步判断确实和 mimetype 有关。浏览源码的时候发现一个工具 kmimetypefinder5,这部分代码看起来对于追踪 KDE 处理 mimetype 的流程非常有用!我在终端调用 kmimetypefinder5 somefile.xlsx,发现返回结果是 x-ole-stroage,我复现了想要的错误。接下来就是看这个工具的源码,一点一点找在哪里 mimetype 没有正确匹配了。

还好这个工具的源码很简单,我很快发现它是调用 Qt 库中的 QMimeDatabase 来判断 mimetype 的。

所以只能看看 Qt 库在干什么了。首先读了一下对应 Qt 文档,发现只说明了提供的接口,没有介绍判断逻辑。

那么接下来只能读源码了。

Google "QMimeDatabase source" 很快定位到了我想要的东西

Qt Source Code

QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *accuracyPtr) { // First, glob patterns are evaluated. If there is a match with max weight, // this one is selected and we are done. Otherwise, the file contents are // evaluated and the match with the highest value (either a magic priority or // a glob pattern weight) is selected. Matching starts from max level (most // specific) in both cases, even when there is already a suffix matching candidate. 

所以说,KDE 经过一系列调用之后,最终调用 Qt 库中这个函数来获取一个文件的 mimetype, 然后用关联的默认程序来打开文件。

简单阅读注释 + 代码,发现 Qt 是根据文件的扩展名和 Magic Number 共同启发式推断文件的类型。也就是说,如果有多个匹配,Qt 会给这些匹配结果分配权重,然后选择权重最高的匹配结果。

没看多远,我就发现了一条我最想要的匹配规则:如果根据文件扩展名的规则匹配,有唯一的匹配结果,那么立刻返回这个匹配。

 // Pass 1) Try to match on the file name QMimeGlobMatchResult candidatesByName; if (fileName.endsWith(QLatin1Char('/'))) candidatesByName.addMatch(QLatin1String("inode/directory"), 100, QString()); else candidatesByName = findByFileName(QFileInfo(fileName).fileName()); if (candidatesByName.m_allMatchingMimeTypes.count() == 1) { *accuracyPtr = 100; const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0)); if (mime.isValid()) return mime; candidatesByName = {}; } 

看到这里,不需要阅读后面的源码,谜底也已经解开了,解决方案已经有了。让我的系统里对于 .doc 等文件只有一种匹配。

打开 KDE File Associations, 把 WPS 加进来的乱七八糟的 mimetypes 删干净,只留下 XDG 标准定义的文档类型,并且为其设置正确的独立程序,如 *.ppt 默认使用 WPS Presentation 而非 WPS 2019 打开。

测试一下,终于成了!我终于能在 Linux 下不糟心的阅读 Office 文档了!对,我们用 Linux 的就是会糟心这种问题……

TL; DR

一句话解决方案:在系统设置里清理 mimetype,把重复匹配 .doc/.docx/.ppt/.pptx 等等的 mimetype 删的只剩下一个,保证每个后缀名只在一个 mimetype 里出现一次。

如果系统设置里删不掉,就找上文提到的“原始 mimetype 配置文件储存路径”

  • /usr/share/mime/packages
  • ~/.local/share/mime/packages

并用合适的参数调用 update-mime-database

相信被这个问题困扰的 Linux 用户不少,希望能帮到你 :)

感谢阅读

博客原文 https://rapiz.me/2021/fix-wps-mime/

44 条回复    2021-04-15 23:33:15 +08:00
defunct9
    1
defunct9  
   2021-04-13 21:21:16 +08:00 via iPhone
用 office 365 它不香吗
delectate
    2
delectate  
   2021-04-13 21:23:05 +08:00   1
libreoffice 它不香吗?
weyou
    3
weyou  
   2021-04-13 21:32:40 +08:00 via Android
为楼主的探索精神点赞
baozijun
    4
baozijun  
   2021-04-13 21:32:43 +08:00 via iPhone
@defunct9 linux 有 office365 ?
hs0000t
    5
hs0000t  
   2021-04-13 21:38:21 +08:00 via Android
深度好文,给楼主赞一个,看来在文件关联这方面还是 Windows 好用
Osk
    6
Osk  
   2021-04-13 22:06:51 +08:00
@baozijun office 365 网页版 /doge/
Jirajine
    7
Jirajine  
   2021-04-13 22:09:00 +08:00 via Android   1
@hs0000t 并不是,Windows 那一大坨注册表更恶心。
不过折腾 wps 这种是真没必要,libreoffice 完全足够,再不济也有 ms 和 Google 的网页版 office 套件。
Osk
    8
Osk  
   2021-04-13 22:09:08 +08:00
给楼主的折腾精神点赞.


虽然我用 o-n-l-y-o-f-f-i-c-e 云办公
defunct9
    9
defunct9  
   2021-04-13 22:46:38 +08:00 via iPhone
libreoffice 、onlyoffice 、wps 都在我电脑上装着,但现在用的最多的是 office 365,它本身是网页版。其他东西都有不同程度的不兼容,这个就完美了
Vegetable
    10
Vegetable  
   2021-04-13 23:02:12 +08:00   21
wps 是用爱发电,原生支持 linux,却一直被骂,成天和 libreoffice 比,也真是令人唏嘘。
大家都像微信 qq 一样大家就都开心了吧
CallMeReznov
    11
CallMeReznov  
   2021-04-13 23:04:23 +08:00   1
LZ 让我想起来给 R 星优化 3 忆次循环的那个大佬...
huaxianyan
    12
huaxianyan  
   2021-04-13 23:10:53 +08:00
好文,学习了
jinliming2
    13
jinliming2  
   2021-04-14 01:11:45 +08:00   2
@Vegetable 既然你提到了 QQ,那你就应该知道,即便是用爱发电出了官方原生的 QQ for Linux,但是做的不用心那还真不如不做,QQ for Linux 做出来就是拿来恶心人的,就是拿来挨骂的。

虽然 WPS 还不至于到 QQ for Linux 那种纯粹恶心人的程度,WPS 在所有国产的 Linux 软件中算是非常优秀的存在了。
但是这样惰性的维护,一堆小问题几年都不修复的,让人处于一种想用又不想用的状态才是最糟糕的。
想用,是他们的确用爱发电,原生支持 Linux,国产能这么良心怎么也得支持一下吧,为国产 Linux 良心软件的良性循环做贡献。
不想用,是里面总是有一堆恶心人的小问题,几年不修复的,但都是那种忍一忍变通一下又能克服的问题,让你没有十足的抛弃它的理由。
dingwen07
    14
dingwen07  
   2021-04-14 04:25:44 +08:00 via Android
好文

Linux 上一般用 Libre Office,需要功能和兼容性就 Office Online,体验其实不错。WPS 没装,虽然 WPS 可能是最好的。
murmur
    15
murmur  
   2021-04-14 08:18:09 +08:00
@delectate libreoffice 的兼容性有问题,他的 excel 不支持跨表引用缺失子表,office 对于跨表引用如果子表丢失,是显示最后的值,但是不会报错,当然重新计算也不可能,libreoffice 直接就###了
james504
    16
james504  
   2021-04-14 08:34:20 +08:00
感谢楼主分享
div id="r_10436598" class="cell">
pisc
    17
pisc  
   2021-04-14 08:42:07 +08:00 via Android
@jinliming2 WPS Linux 有一个专门的团队维护,遇到问题可以直接跟他们反馈,至于怎么反馈,你在知乎上找找,另外他们相对精力会放在 Ubuntu 这样的发行版,Arch Linux 出的问题,可能要找社区来修
no1xsyzy
    18
no1xsyzy  
   2021-04-14 09:24:14 +08:00
@Vegetable WPS 原生支持 Linux 是用爱发电?不是瞄准国家战略方向吗?
魔都,官方采购预装已经是中标麒麟了哦
ihipop
    19
ihipop  
   2021-04-14 09:26:55 +08:00 via Android
为啥我也是基于 Arch 的 manjaro KDE 没这问题?只要设置一次默认打开方式就行?也装了 WPS MIME 这个包的
0TSH60F7J2rVkg8t
    20
0TSH60F7J2rVkg8t  
   2021-04-14 09:42:56 +08:00   2
感谢楼主分享

不过说个意见啊,TL;DR 不应该放在最开始吗?这不是总结的意思,这是 Too long, don't read (太长别读)的意思,一般是放在文章开头,有人不愿意看长文的可以先读这块,或者直接绕道走。您这 TL;DR 放结尾,我看完了整篇才看到它。
baozijun
    21
baozijun  
   2021-04-14 11:50:44 +08:00 via iPhone   1
@no1xsyzy wps for linux 在战略之前就出了而且一直在维护,应该是得益于 qt 的跨平台,那时就是社区的呼吁才推出的,就是用爱发电。
catchexception
    22
catchexception  
   2021-04-14 14:24:47 +08:00
抄送我们的 飞哥 https://cryfeifei.cn/
cyspy
    23
cyspy  
   2021-04-14 14:41:31 +08:00
只有一种匹配是个 workaround,还是要看下为什么多种匹配情况下不想要的那个权重跑到了最高
aneostart173
    24
aneostart173  
   2021-04-14 15:48:05 +08:00
最近试了试 libreoffice,除了界面略显原始,其他都挺好。wps 感觉一直在更新界面,内容没啥变化。
bsidb
    25
bsidb  
   2021-04-14 16:00:30 +08:00   1
@aneostart173 WPS 最近一版还是更新了不少东西的。WPS Linux 下也能用云办公,而且和 Windows 下使用体验很接近,好良心。WPS Linux 下还有 Windows 没有的 Office 07 版本的公式。现在 Windows 下的 WPS 还是用的 MathType 插入公式,WPS 的 Linux 版已经原生支持 Office 公式了,相当良心。
villivateur
    26
villivateur  
   2021-04-14 16:14:44 +08:00 via Android   1
一楼二楼什么鬼,楼主是在分享技术探索经历
Smash
    27
Smash  
   2021-04-14 16:31:29 +08:00 via Android
我 wps 会员都开了两年多了,真的好用
mangosong
    28
mangosong  
   2021-04-14 16:33:30 +08:00
厉害了 寻根问底
XYSKYZ
    29
XYSKYZ  
   2021-04-14 16:51:37 +08:00
QT 库原来是开源的?!
gdtdpt
    30
gdtdpt  
   2021-04-14 18:26:40 +08:00
点赞
ciaoly
  &nsp; 31
ciaoly  
   2021-04-14 19:09:35 +08:00 via Android
WPS 4 Linux 很优秀啊,为什么 v2er 的意见这么大呢?买个会员也不贵啊网速还比 1drive 快得很,1drive 同步起来真的难受
wzzzx
    32
wzzzx  
   2021-04-14 20:23:18 +08:00
很赞!
CismonX
    33
CismonX  
   2021-04-14 20:43:46 +08:00 via iPhone
@ahhui

TL;DR 表示“总结”的用法也可以,我见过一些。但这种用法往往是作者的自嘲,表达出一种“前面的都是废话,直接看总结就够了”的意味。
FurN1
    34
FurN1  
   2021-04-14 21:11:55 +08:00
点赞!
solider245
    35
solider245  
   2021-04-14 21:56:36 +08:00   4
楼主这种精神才是码农精神,很多伟大的事情都是从解决长期困扰的一个小问题开始的.
wangkun025
    36
wangkun025  
   2021-04-14 21:59:51 +08:00
TLDR 的用法好像是相反的。
wzxlovesy
    37
wzxlovesy  
   2021-04-15 04:22:36 +08:00 via Android
赞楼主
vhysug01
    38
vhysug01  
   2021-04-15 08:51:49 +08:00 via iPhone
虽然我没看完,但是楼主牛逼
GM
    39
GM  
   2021-04-15 08:57:55 +08:00
WPS 一向有这种自作主张自作聪明乱改系统设置的行为,我都碰到 N 次了,办公室文员电脑上尤为常见。

最容易出现的路径是:莫名其妙点了个确定,被自动装各种全家桶,包括 WPS,然后内嵌了 excel 导出、word 打印之类的程序莫名其妙就用不了了,怎么修复打开方式都无效,解决方法是卸载掉 WPS,重新安装一次 ms office,马上 OK 。
Manley
    40
Manley  
   2021-04-15 09:30:53 +08:00 via Android   1
分享一个自己的经历,公司平台的上传下载在国产系统的桌面上工作异常,因为过不去上传时候的 mime 类型检查,就是因为 wps 把系统的 mime 类型改了,.docx .pptx .xlsx 文件的 mime 类型跟微软的对不起来。。。简直是迷惑操作...
0TSH60F7J2rVkg8t
    41
0TSH60F7J2rVkg8t  
   2021-04-15 10:40:46 +08:00
@CismonX 多谢指教!
Cu635
    42
Cu635  
   2021-04-15 10:42:27 +08:00
@XYSKYZ
开源,而且是 GPL 加上商业许可证的双许可协议。
evilStart
    43
evilStart  
   2021-04-15 22:23:18 +08:00 via Android
虽然我用不到,但还是很佩服作者的行动力,这才是 V2EX 该有的样子
Owenjia
    44
Owenjia  
   2021-04-15 23:33:15 +08:00
wps4linux 的维护团队感觉是换人了,明显的感觉到初期的维护者是比较有追求的。
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2920 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 29ms UTC 13:47 PVG 21:47 LAX 05:47 JFK 08:47
Do have faith in what you're doing.
ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86