![如何找到非默认状态菜单(又名指示器)使用的图标文件?](https://linux22.com/image/1141012/%E5%A6%82%E4%BD%95%E6%89%BE%E5%88%B0%E9%9D%9E%E9%BB%98%E8%AE%A4%E7%8A%B6%E6%80%81%E8%8F%9C%E5%8D%95%EF%BC%88%E5%8F%88%E5%90%8D%E6%8C%87%E7%A4%BA%E5%99%A8%EF%BC%89%E4%BD%BF%E7%94%A8%E7%9A%84%E5%9B%BE%E6%A0%87%E6%96%87%E4%BB%B6%EF%BC%9F.png)
我想找到一些非默认使用的图标的位置状态菜单(也称为应用程序指示器或指示器小程序)。
这些图标图像文件位于哪里?
在我的屏幕截图中,我有 ownCloud 和 Radiotray,但我希望得到一个通用答案,而不是针对这些特定图标。我不知道文件名或文件类型,因此搜索很困难。
答案1
非默认指示图标的默认位置?
这些图标没有默认的存储位置。任何应用程序(开发人员)都可以将它们存储在其认为合适的位置。
然而,好消息是,指标通常不会安装无穷无尽的文件和图像列表。我们可以通过(除了查看代码)查看命令的输出来限制我们的搜索:
dpkg-query -L <packagename>
在我的例子中
dpkg-query -L placesfiles
除其他外,这将输出以下图像:
/opt/placesfiles/images/dir_icon.png
/opt/placesfiles/images/placesfiles64.png
/usr/share/pixmaps/placesfiles.png
...这会使搜索范围变得十分有限。
来自 man dpkg-query
:
-l, --list [package-name-pattern...]
List packages matching given pattern. If no package-name-pattern
is given, list all packages in /var/lib/dpkg/status, excluding
the ones marked as not-installed (i.e. those which have been
previously purged). Normal shell wildcard characters are allowed
in package-name-pattern. Please note you will probably have to
quote package-name-pattern to prevent the shell from performing
filename expansion. For example this will list all package names
starting with “libc6”:
如果是无线电托盘,我发现以下.png
文件(正在运行dpkg-query -L radiotray | grep png
):
/usr/share/radiotray/images/radiotray_connecting.png
/usr/share/radiotray/images/radiotray_on.png
/usr/share/radiotray/images/radiotray_off.png
/usr/share/radiotray/images/radiotray.png
/usr/share/pixmaps/radiotray.png
要是我们真的需要找出答案,搜索代码
...我们可以在已安装的文件中查找字符串“icon”的匹配项。许多指标都是用脚本语言(如python
)编写的,这意味着它们非常适合搜索。
一个例子
再次使用radiotray
示例
dpkg-query -L radiotray | xargs grep icon
在输出中我们发现 ao:
/usr/lib/python2.7/dist-packages/radiotray/SysTrayGui.py
self.icon.set_from_file(APP_ICON_CONNECT)
查看该文件SysTrayGui.py
,我们可以看到:
from lib.common import APPNAME, APPVERSION, APP_ICON_ON, APP_ICON_OFF, APP_ICON_CONNECT, APP_INDICATOR_ICON_ON, APP_INDICATOR_ICON_OFF
由此,我们可以得出结论,所提到的图标是在common
(子)目录内的模块中定义的lib
。(参见这里Python 如何找到模块、部分子目录)
在此模块中,我们可以阅读以下部分:
# Media path
if os.path.exists(os.path.abspath('../data/images/')):
IMAGE_PATH = os.path.abspath('../data/images/')
else:
IMAGE_PATH = '%s/%s/images' % (datadir, APPDIRNAME)
# Images
APP_ICON = os.path.join(IMAGE_PATH, 'radiotray.png')
APP_ICON_ON = os.path.join(IMAGE_PATH, 'radiotray_on.png')
APP_ICON_OFF = os.path.join(IMAGE_PATH, 'radiotray_off.png')
APP_ICON_CONNECT = os.path.join(IMAGE_PATH, 'radiotray_connecting.gif')
APP_INDICATOR_ICON_ON = "radiotray_on"
APP_INDICATOR_ICON_OFF = "radiotray_off"
APP_INDICATOR_ICON_CONNECT = "radiotray_connecting"
...我们就在这里...
特殊情况
通过实际使用我的所有指标,我设法使用上述方法找到了相应的图标。
但事实证明,可以将图像与代码一起编译成单个可执行文件。无需解释,在这种情况下,您将找不到单独的图像,也无法在不编辑代码并重新编译的情况下替换它们。
owncloud 的情况似乎就是这样。使用上述方法显示里面安装了一组图标/usr/share/icons/hicolor/<size>/apps
。然而,这些图标都没有在指示器中使用在 Ubuntu 上。
OP 在提出这个问题之前 (和之后) 做了大量工作。其中之一就是运行:
gdbus call --session --dest com.canonical.indicator.application --object-path /com/canonical/indicator/application/service --method com.canonical.indicator.application.service.GetApplications
...这给了我们很多有用的信息。输出包括以下部分:
('146028888067', 2, 'org.kde.StatusNotifierItem-22055-1', '/StatusNotifierItem/menu', '/tmp/iconcache-50ePXx', '', '', '', 'owncloud', 'ownCloud')
查看目录/tmp/iconcache-50ePXx
,我发现了指标使用的确切图标:
...这似乎证明这些图标是即时生成的;关闭 owncloud 会导致目录及其图标消失。
事实证明,通过替换这些图标可以更改指标的图标:
这证明这些确实是我们正在寻找的图标。
然而,要自动执行我手动执行的操作,则需要脚本/包装器,因为每次启动 owncloud 时,创建的目录名称都会更改。最方便的选择当然是更改 owncloud-client 的代码。
另请参阅我们的讨论这里。
待续...
答案2
图标及其可能的位置
指示器可以使用两种图标的方式:
- 自定义图标。这通常会进入
/usr/share/pixmaps/
,尽管有些作者可能会将指示器图标发送到其他目录。例如,Jacob Vlijm(他的答案在本页上,他也是 SpaceView 指示器的作者)选择将该指示器的图标放入/opt/spaceview/icon
。对于这些类型的图标,有点棘手但并不复杂 - 使用dpkg -L <package name>
或并搜索带有或扩展名cat /var/lib/dpkg/info/PACKAGE.list
的图标文件。这些是最典型的.png
.svg
- 标准、主题特定的图标。这些通常可以在
/usr/share/icons
文件夹中找到。例如,在我的指示器(如 Udisks 指示器)中,我经常依赖 中的内容/usr/share/icons/gnome
,因为它们是标准的,并且随任何 Ubuntu 安装一起提供。如果您在查询 时找不到图标dpkg
,则很可能该包使用了标准图标。
追根溯源
如果指示器是用 Python 或 Ruby 编写的,那么通过源代码寻找线索会相对容易,因为这些都是脚本,使用它grep
来搜索源代码就足够了。编译语言(例如 C 和 Vala)不附带源代码,因此您必须通过apt-get source package-name
或从您获得软件包的地方获取它。(喜欢冒险的用户可以使用hexdump
或反编译可执行文件,但恕我直言,仅仅因为对图标的好奇心,这太麻烦了)。
笔记:如果图标位于标准目录之一(例如/usr/share/icons/
或 )中/usr/share/pixmaps
,软件作者可以选择仅通过名称来调用图标,而不使用扩展名。例如,在我的 中,udisks-indicator
我使用此行来调用标准图标之一:
self.app.set_icon("drive-harddisk-symbolic")
请注意缺少.svg
或.png
扩展名。因此,在这种情况下,我们有一个图标的名称,我们可以使用 Linux 标准命令(例如locate
或 )找到它find
。
使用标准 Linux 工具进行搜索
如果您确实想要一个搜索图标的命令,只需使用这个简单的组合:
dpkg -L <Package name here> | xargs file | grep -i image
这是一个例子。我知道指示器 diskman 使用自定义图标。那么这个命令告诉我们什么?
$ dpkg -L indicator-diskman | xargs file | grep -i image
/usr/share/indicator-diskman/images: directory
/usr/share/indicator-diskman/images/drive-harddisk.svg: SVG Scalable Vector Graphics image
/usr/share/indicator-diskman/images/media-optical.png: PNG image data, 64 x 64, 8-bit/color RGBA, non-interlaced
/usr/share/indicator-diskman/images/disks.png: PNG image data, 64 x 64, 8-bit gray+alpha, non-interlaced
/usr/share/indicator-diskman/images/locked.png: PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced
/usr/share/indicator-diskman/images/lock.svg: SVG Scalable Vector Graphics image
/usr/share/indicator-diskman/images/unlocked.png: PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced
/usr/share/indicator-diskman/images/media-eject.svg: SVG Scalable Vector Graphics image
/usr/share/indicator-diskman/images/disk.png: PNG image data, 32 x 32, 8-bit/color RGBA, non-interlaced
/usr/share/pixmaps/indicator-diskman.png: PNG image data, 64 x 64, 8-bit gray+alpha, non-interlaced
注意/usr/share/pixmaps/indicator-diskman.png
最后一张图片,这是指示器在面板上实际显示的内容。
如果指示器使用标准图标怎么办?显然不会有输出:
$ dpkg -L udisks-indicator | xargs file | grep -i image
$
结论
虽然没有固定的标准,但图标有一套典型的放置位置,我们可以使用它们dpkg
来查询每个特定软件包附带的文件信息。最后,也许这不是最技术性的建议,但可以考虑给开发人员发送电子邮件或在他们的 IRC 或聊天室停留,然后简单地问他们“嘿,你的指示器使用什么图标?”。开发人员通常很高兴听到使用他们软件的人的来信,并且不介意回答一个简单的问题。