KDE 配置文件中值开头的感叹号有什么作用?

Vin*_*nce 2 kde configuration

在 中~/.kde/share/config/kdeglobals,默认 Web 浏览器的值以感叹号开头。感叹号的用途是什么?

[General]
BrowserApplication[$e]=!sensible-browser
Run Code Online (Sandbox Code Playgroud)

Eli*_*bst 5

顺便问一下源代码。如果你对细节不感兴趣,直接跳到最后看结果:

有一个用于设置默认应用程序的 KCM。我们来看看它的名字:

$ kcmshell4 --list | ack -i default
componentchooser           - Choose the default components for various services
Run Code Online (Sandbox Code Playgroud)

注意:以下 5 个步骤是 Gentoo 特定的,但可以应用于任何其他发行版,或者可以通过手动浏览 KDE 的源代码库来替换!

让我们在文件系统中搜索属于以下内容的文件componentchooser

$ find /usr -name "*componentchooser*"
/usr/lib64/kde4/kcm_componentchooser.so
/usr/share/doc/HTML/en/kcontrol/componentchooser
/usr/share/doc/HTML/de/kcontrol/componentchooser
/usr/share/kde4/services/componentchooser.desktop
/usr/share/apps/kcm_componentchooser
/usr/share/locale/de/LC_MESSAGES/kcmcomponentchooser.mo
Run Code Online (Sandbox Code Playgroud)

现在我们将查询包管理器(在我们的例子中是 Gentoo 的 Portage)并询问包含以下任何文件的包:

$ find /usr -name "*componentchooser*" | xargs qfile
kde-base/kdelibs (/usr/share/apps/kcm_componentchooser)
kde-base/kcontrol (/usr/share/apps/kcm_componentchooser)
kde-base/kcontrol (/usr/share/kde4/services/componentchooser.desktop)
kde-base/kcontrol (/usr/share/doc/HTML/en/kcontrol/componentchooser)
kde-base/kcontrol (/usr/lib64/kde4/kcm_componentchooser.so)
kde-base/kde-l10n (/usr/share/locale/de/LC_MESSAGES/kcmcomponentchooser.mo)
kde-base/kde-l10n (/usr/share/doc/HTML/de/kcontrol/componentchooser)
Run Code Online (Sandbox Code Playgroud)

当我们在寻找实际为默认浏览器写入值的源代码时,我们应该查看.so包含实际代码的文件,而其他文件只提供文档 ( /usr/share/doc/[…])、元信息 ( […].desktop) 和翻译字符串 ( /usr/share/locale/[…])。

这意味着,我们必须查看提供共享对象 ( .so) 文件的包,该文件kde-base/kcontrol位于 Gentoo 上。

首先,我们确保源 tarball 存在于我们的文件系统中,通过要求 Portage 为这个包下载它(--nodeps确保只下载这个包的源,而不是任何依赖项):

$ emerge --fetchonly --nodeps kde-base/kcontrol
>>> Fetching (1 of 1) kde-base/kcontrol-4.11.4
 * kde-runtime-4.11.4.tar.xz SHA256 SHA512 WHIRLPOOL size ;-) ...    [ ok ]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,文件已经存在并且只验证了它的校验和。

现在我们要将这个文件解压到一个临时位置以进一步检查它:

$ cd /tmp
$ tar xf /usr/portage/distfiles/kde-runtime-4.11.4.tar.xz
Run Code Online (Sandbox Code Playgroud)

结果是kde-runtime-4.11.4我们现在要更改的目录:

$ cd kde-runtime-4.11.4
Run Code Online (Sandbox Code Playgroud)

这个目录现在包含了很多属于kde-runtimeKDE SC 包的组件。我们对kcontrol组件感兴趣:

$ cd kcontrol
Run Code Online (Sandbox Code Playgroud)

现在我们需要确定包含将默认浏览器写入的源代码的文件kdeglobalsrc。有不同的方法可以做到这一点:

  1. 浏览目录结构并尝试按名称查找文件。
  2. 查找名称包含类似内容的文件componentchooser并检查其源代码
  3. 扫描源码,直接找到写入值的文件BrowserApplication

我们目标的最短路径是选项“3”,这就是我们要做的:

$ ack BrowserApplication
componentchooser/componentchooserbrowser.cpp
50:    QString exec = config.readPathEntry( QLatin1String("BrowserApplication"), QString("") );
92:    config.writePathEntry( QLatin1String("BrowserApplication"), exec); // KConfig::Normal|KConfig::Global
Run Code Online (Sandbox Code Playgroud)

很明显,在文件的第 92 行componentchooser/componentchooserbrowser.cpp,就是正在写入这个值,所以让我们仔细看看它:

 80 void CfgBrowser::save(KConfig *)
 81 {
 82     KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), QLatin1String("General") );
 83     QString exec;
 84     if (radioExec->isChecked())
 85     {
 86         exec = lineExec->text();
 87         if (m_browserService && (exec == m_browserExec))
 88             exec = m_browserService->storageId(); // Use service
 89         else if (!exec.isEmpty())
 90             exec = '!' + exec; // Literal command
 91     }
 92     config.writePathEntry( QLatin1String("BrowserApplication"), exec); // KConfig::Normal|KConfig::Global
 93     config.sync();
 94
 95     KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged);
 96
 97     emit changed(false);
 98 }
Run Code Online (Sandbox Code Playgroud)

在第 92 行,键BrowserApplication被写入,它的值在变量中exec。感叹号被添加到“90”行的命令字符串中,但在这一行的代码中没有详细的注释来解释为什么这样做,所以让我们看看导致添加的代码逻辑一个!在前面的BrowserApplication值:

  • 第 86 行设置exec为输入字段提供的字符串
  • '87'行检查成员变量是否m_browserService为真,变量的内容是否与成员变量exec相同m_browserExec
    • m_browserService当通过浏览应用程序树而不是直接将可执行文件名称作为字符串输入来选择默认浏览器时,由方法 CfgBrowser::selectBrowser设置(01)。如果通过浏览应用程序树选择浏览器,则输入字段的内容是应用程序*.desktop文件的名称。
    • m_browserExec*.desktop通过应用程序树选择浏览器时的文件名。
    • 如果两个语句的计算结果都为TRUEexec则设置为storageId*.desktop条目名称)的结果。
    • 否则,将设置可执行文件的名称,但在它前面加上!.

简而言之:

BrowserApplication条目中的感叹号kdeglobalsrc用于区分为启动浏览器而执行的实际二进制名称或浏览器*.desktop文件的名称。