V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
rapiz
V2EX  ›  Linux

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

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

问题背景和表现

如果你使用 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
感谢楼主分享
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 这个包的
ahhui
    20
ahhui  
   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
    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 表示“总结”的用法也可以,我见过一些。但这种用法往往是作者的自嘲,表达出一种“前面的都是废话,直接看总结就够了”的意味。
IgniteWhite
    34
IgniteWhite  
   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 类型跟微软的对不起来。。。简直是迷惑操作...
ahhui
    41
ahhui  
   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   ·   我们的愿景   ·   实用小工具   ·   3166 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 32ms · UTC 12:26 · PVG 20:26 · LAX 05:26 · JFK 08:26
Developed with CodeLauncher
♥ Do have faith in what you're doing.