How do I find the icon files used by non-default status menus (aka indicators)?

I'd like to find the location of the icons used by some non-default status menus (also called application indicators or indicator applets).

enter image description here

Where are these icons image files located?

In my screenshot I have ownCloud and Radiotray, but I would like a general answer not specific to these particular icons please. I don't know the file names or file types so searching is difficult.


Default location for non-default indicator icons?

There is no default location where these icons are stored. Any application (-developer) can store them where it is considered appropriate.

However, the good news is that indicators usually do not install endless lists of files and images. We can limit our search by (apart from looking into the code) looking into the output of the command:

dpkg-query -L <packagename>

In my example of

dpkg-query -L placesfiles

enter image description here

this would among others, output the following images:

/opt/placesfiles/images/dir_icon.png
/opt/placesfiles/images/placesfiles64.png
/usr/share/pixmaps/placesfiles.png

...Which would make the search quite limited.

From 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”:

In the case of Radiotray, I found the following .png files (running 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

If we really need to find out, searching the code

...we can look through (inside) installed files for matches of the string "icon". Many of the indicators are written in one of the script- languages (like python), which means they are very well search-able.

An example

Again using the radiotray example

dpkg-query -L radiotray | xargs grep icon

in the output we find a.o.:

/usr/lib/python2.7/dist-packages/radiotray/SysTrayGui.py 
                 self.icon.set_from_file(APP_ICON_CONNECT)

Looking into the file SysTrayGui.py, we can see:

from lib.common import APPNAME, APPVERSION, APP_ICON_ON, APP_ICON_OFF, APP_ICON_CONNECT, APP_INDICATOR_ICON_ON, APP_INDICATOR_ICON_OFF

From this, we can conclude the mentioned icons are defined in the module common inside the (sub) directory lib. (See here how python finds it modules, section Subdirectories)

In this module, we can read the section:

# 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"

...and here we are...

Exceptional situations

With practical all of my indicators, I managed to find the corresponding icons using the method(s) above.

In turns out to be possible however, to compile images together with the code into a single executable. No need to explain that in such cases you will not find a separate image, nor will you be able to replace them without editing the code and recompile.

The case of owncloud seems to be such a case. Using the above method(s) showed a set of icons was installed inside /usr/share/icons/hicolor/<size>/apps. None of these icons turns out to be used however in the indicator on ubuntu.

OP did quite some work before (and after) he asked this question. One of them was to run:

gdbus call --session --dest com.canonical.indicator.application --object-path /com/canonical/indicator/application/service --method com.canonical.indicator.application.service.GetApplications

... which gives us quite some useful information. The output included a section:

('146028888067', 2, 'org.kde.StatusNotifierItem-22055-1', '/StatusNotifierItem/menu', '/tmp/iconcache-50ePXx', '', '', '', 'owncloud', 'ownCloud')

Looking into the directory /tmp/iconcache-50ePXx, I found the exact icons that were used by the indicator:

enter image description here enter image description here enter image description here

... which seems to prove these icons are generated on the fly; closing owncloud makes the directory and its icons vanish.

It turned out to be possible to change the indicator's icon by replacing these icons:

enter image description here

which proves these are indeed the icons we were looking for.

To automate what I did manually however, would requires a script/wrapper, since the created directory's name is changed every time owncloud is launched. The most convenient option would of course be that the owncloud-client's code would be changed.

See also our discussion here.

To be continued...


Icons and their potential locations

There's two ways indicator could employ icons:

  • Custom icon. This typically goes into /usr/share/pixmaps/ , although it's possible some of the authors send indicator icons to other directories. Jacob Vlijm, whose answer is on this page and who is also author of SpaceView indicator, for example, chose to place icons for that indicator into /opt/spaceview/icon. With these type of icons it's slightly tricky but not complex - use dpkg -L <package name> or cat /var/lib/dpkg/info/PACKAGE.list and search for an icon file, with .png or .svg extension. These are most typical
  • Standard, theme-specific icon. These typically can be found in /usr/share/icons folder. For instance, in my indicators such as Udisks Indicator, I frequently rely on what's in /usr/share/icons/gnome , since these are standard and come with any Ubuntu installation. If you don't find an icon from querying dpkg , chances are the package uses a standard icon.

Going to the source

If an indicator is written in Python or Ruby, looking through source code for clues can be relatively easy, since these are scripts, and it is sufficient to use grep to search through the source code. Compiled languages such as C and Vala don't come with source code, so you would have to obtain it, either via apt-get source package-name or from wherever you obtained the package. ( Adventurous users could use hexdump or decompile the executable file, but IMHO it's too much work just for curiosity about an icon ).

NOTE: if an icon resides in one of the standard directories, such as /usr/share/icons/ or /usr/share/pixmaps, the author of the software may choose to call the icon simply by name, without extensions. For example, in my udisks-indicator I use this line to call one of the standard icons:

self.app.set_icon("drive-harddisk-symbolic")

Notice the lack of .svg or .png extension. Thus, in this case, we have a name of the icon, and we can locate it using Linux standard commands such as locate or find.

Search using standard Linux tools

If you really want to have a command for searching icons, just use this simple combination:

dpkg -L <Package name here> | xargs file  | grep -i image

Here's an example. I know for a fact that indicator diskman uses a custom icon. So what does this command tell us ?

$ 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

Notice the /usr/share/pixmaps/indicator-diskman.png the last image, which is what the indicator actually shows on the panel.

And what if the indicator uses a standard icon ? Well obviously there will be no output:

$ dpkg -L udisks-indicator | xargs file  | grep -i image                                                                 

$

Conclusion

While there's no set standard, there's set of typical places where icons go, and we can use dpkg to query information about what files come with each specific package. Finally, maybe it's not the most technical suggestion, but consider sending developers an email or stopping by their IRC or chat, and simply asking them "Hey, what icon does your indicator use?". Developers usually are glad to hear from people who use their software and won't mind to answer a quick question.