CSS-based styling

Before IDA 7.3

IDA used to store colors in the registry:

  • HKEY_CURRENT_USER\Software\Hex-Rays\IDA on Windows,

  • ~/.idapro/ida.reg on Linux & Mac OSX.

This was somewhat inconvenient because color values were stored in binary format, and hard to move from computer to computer.

In addition, this only lets users style a small subset of the widgets that compose IDA, which can be insufficient.

IDA 7.3: CSS-based styling

Since we had to introduce yet another set of new colors in 7.3, we took the opportunity to moved away from the registry-stored, binary-only approach, to a CSS-based approach.

This gives us the following advantages:

  • CSS is a well-known format

  • CSS is human-readable

  • Qt understands CSS out-of-the-box (parts of it, at least)

  • Using CSS will therefore let us style not only the custom IDA widgets, but all widgets

This last point is important, because many users have been asking for the ability to style IDA more thoroughly, rather than just styling a few custom widgets (such as the disassembly views, navigation band, …)

How IDA 7.3 CSS-based styling works

IDA 7.3 ships with 2 themes by default:

  • default

  • dark

Those themes are located in $IDA_INSTALL/themes/:

aundro@flatiron:~/IDA-7.3$ tree themes/
themes/
├── _base
│   └── theme.css
├── dark
│   ├── icons
│   │   ├── expand.png
│   │   └── spacer.png
│   └── theme.css
└── default
    └── theme.css

4 directories, 5 files
aundro@flatiron:~/IDA-7.3$

Notice that, in addition to dark and default directories, you can also spot an additional _base directory.

The _base theme holds all the CSS directives that are required for IDA to work correctly, and therefore it must be “imported” by other themes (using the IDA-specific @importtheme directive) before any other styling directives are declared.

For example, here are the first 3 lines of $IDA_RELEASE/themes/dark/theme.css:

aundro@flatiron:~/IDA-7.3$ head -n 3 themes/default/theme.css

@importtheme "_base";

aundro@flatiron:~/IDA-7.3$

What happens when colors are modified through the “Colors” dialog?

When you change colors in the ‘Colors’ dialog, IDA will not modify the files that are present in $IDA_INSTALL/themes/.

Instead, IDA will create a file in IDA’s user directory, holding what we will refer to as “user overrides”.

Let’s assume the user:

  • switched to the dark theme,

  • modified the Instruction text color to red.

  • clicked ‘OK’

IDA will then have created the file:

  • ~/.idapro/themes/dark/user.css

  • %APPDATA%\Hex-Rays\IDA Pro\themes\dark\user.css on Windows

with the following contents:

aundro@flatiron:~/.idapro$ tree themes
themes
└── dark
    └── user.css

1 directory, 1 file
aundro@flatiron:~/.idapro$
aundro@flatiron:~/.idapro$ cat themes/dark/user.css
/* NOTE: This is an autogenerated file; please do not edit. */

CustomIDAMemo
{
    qproperty-line-fg-insn: red;
}
aundro@flatiron:~/.idapro$

In other words, the themes that are shipped with IDA are never modified, but instead a “user override” file is created, that will contain whatever customization the user made to the theme.

Importing/Exporting themes customization

IDA 7.3 removed the Import/Export feature from its Colors dialog, because an equivalent is already automatically present in the form of those “user overrides” files, which can be found in:

  • %APPDATA%\Hex-Rays\IDA Pro\themes\*\user.css on Windows,

  • ~/.idapro/themes/*/user.css on Linux and Mac OSX.

In order to re-use customizations across different computers, it is enough to just copy those user.css file(s).

Debugging style sheets lookup

In case IDA misbehaves, and appears to ignore some styling directives, it’s possible to launch IDA with the following command-line flag to debug themes loading: ida -z1000000

In IDA’s Output window, you should spot something along the lines of this:

Themes: Trying file "/home/aundro/IDA-7.3/themes/dark/theme.css" ... found.
Themes: Trying file "/home/aundro/.idapro/themes/dark/theme.css" ... not found.
Themes: Found @importtheme (/home/aundro/IDA-7.3/themes/dark/theme.css:6)
Themes: Trying file "/home/aundro/IDA-7.3/themes/_base/theme.css" ... found.
Themes: Trying file "/home/aundro/.idapro/themes/_base/theme.css" ... not found.
Themes: Trying file "/home/aundro/IDA-7.3/themes/dark/user.css" ... not found.
Themes: Trying file "/home/aundro/.idapro/themes/dark/user.css" ... found.

First of all, IDA tries to load the desired (dark) theme contents (that corresponds to the first 5 lines):

  • IDA looked for $IDA_INSTALL/themes/dark/theme.css, and found it

  • IDA also looked for ~/.idapro/themes/dark/theme.css! (we’ll discuss this in the following chapter)

  • IDA spotted that the dark theme imports the _base theme, and loaded contents from that one as well.

Then, IDA tries to load user overrides for the dark theme (corresponds to the 2 final lines):

  • IDA looked for $IDA_INSTALL/themes/dark/user.css, but didn’t find it (this is, in fact, pretty much unnecessary, since user overrides should never be in IDA’s installation directory. We’ll eventually get rid of this.)

  • IDA looked for in ~/.idapro/themes/dark/user.css, and found it.

Adding themes

As was mentioned in the previous chapter, IDA also looks for themes contents in IDA’s user directory:

  • %APPDATA%\Hex-Rays\IDA Pro\themes on Windows,

  • ~/.idapro/themes on Linux & Mac OSX

That means it’s possible to add your own themes there, without having to modify the (possibly read-only) $IDA_INSTALL directory.

In addition, putting additional themes in IDA’s user directory means that new version of IDA will be able to pick them up automatically.

Example new theme

Let’s say you want to create a new theme, called blue.

You should therefore create the following CSS file:

  • ~/.idapro/themes/blue/theme.css

…in which you can override anything you want, after importing the _base theme.

For example:

aundro@flatiron:~/.idapro$ cat themes/blue/theme.css

@importtheme "_base";

QWidget
{
    background-color: lightblue;
}

CustomIDAMemo
{
    qproperty-line-fg-regular-comment: red;
    [...snipped...]
}
aundro@flatiron:~/.idapro$

You can then ship that ~/.idapro/themes/blue/theme.css file to other users, and any personal modifications they make to it, will be stored in ~/.idapro/themes/blue/user.css, leaving your original blue theme untouched.

What can be styled, and how?

Conceptually, IDA’s CSS styling can be “split” into 2 categories:

  1. Core Qt widgets styling

  2. IDA custom widgets styling

1) Core Qt widgets styling

In order to know what, and how to style Qt widgets, the best is to have a look at the references:

2) IDA custom widgets styling

IDA’s main stylable custom widgets have the following class names:

  • CustomIDAMemo

  • TextArrows

  • MainMsgList

  • TCpuRegs

  • navband_t

You can find the entire set of properties supported by those, by looking at the contents of:

  • $IDA_INSTALL/themes/_base/theme.css

  • $IDA_INSTALL/themes/default/theme.css

A note about the “.clr” file format

In order to re-use color schemes with IDA < 7.3, users had to export, and then import them using .clr files.

It’s worth pointing out that colors in those files, are in the form "BBGGRR", while CSS expects "#RRGGBB", so you will need to pay attention to that when porting colors from a .clr file.

Alternatively, you can use the following script, which might help get most of the job done.

A note about the dark theme

Note that even though IDA ships with a ‘dark’ theme, the version of Qt we use still doesn’t support OS-induced theme switches, and therefore IDA won’t automatically switch to it; the user will still have to change it manually.

Restrictions

Qt is mostly stylable using CSS, but it has a few restrictions:

  • Styling of URLs in QLabel instances is not supported (see this question)

  • In tabular views (e.g., the Functions window widget), we added the ability to highlight the portions of text that match the “quick filter” query (which can be opened using Ctrl+F). Unfortunately, the code we added to do that, will simply not be called for items in those views to which CSS directives apply. This is the case for e.g., “selected” items, in the dark mode. We will try and solve this in the future, but currently don’t have a fix.

Last updated