Using Font Awesome in QML applications

By Andreas Wilhelm Oct 1, 2015

Today I was wondering if I could use Font Awesome with Qt’s QML to add some nice looking icons to my buttons. A quick google search brought up an article “Using Fonts Awesome in QML” by markg85 at Mark’s KDE Blog. Mark came up with a nice solution that uses a javascript dictionary to store the icon names with their corresponding unicode character:

var Icon = {
    Glass               : "\uf000",
    Music               : "\uf001",
    ...
};

However, this has two problems.

  1. The names in the javascript file do not match the definitions on fontawesome.github.io.
  2. The defintions are outdated and do neither include the latest icons nor alias names.

Funny Fact: It’s actually fortawesome.github.io not fontawesome.github.io.

To fix both issues, I wrote a small python script, which will visit https://fontawesome.github.io/Font-Awesome/icons, extract all icon names and the corresponding icon pages (for example https://fontawesome.github.io/Font-Awesome/icon/cogs) and load the unicode associated with this icon name from the icon page:

#!/usr/bin/python3
import re
import urllib.request
import http.server

def fetchSite(url):
  req = urllib.request.Request(url)
  try:
    with urllib.request.urlopen(req) as response:
      html = response.read()
  except urllib.error.HTTPError as e:
    errorMsg = http.server.BaseHTTPRequestHandler.responses[e.code][0]
    print("Cannot retrieve URL: {} : {}".format(str(e.code), errorMsg))
  except urllib.error.URLError as e:
    print("Cannot retrieve URL: {}".format(e.reason))
  except:
    print("Cannot retrieve URL: unknown error")
    return html

def extractIconLinks(html):
  links = {}
  pattern = r'<div class="fa-hover col-md-3 col-sm-4"><a href="../icon/(.*?)"><i class="fa (.*?)"></i> (.*?)</a></div>'
  for match in re.finditer(pattern, str(html)):
    iconName = match.group(2).partition(' ')[0]
    iconLink = match.group(1)
    if iconName[:3] == "fa-":
      links[iconName] = "{}{}".format("https://fortawesome.github.io/Font-Awesome/icon/", iconLink)

  return links

def extractUnicode(html):
  match = re.search(r'Unicode: <span class="upper">(.*?)</span>', str(html))
  if match:
    return "\\u{}".format(match.group(1))
  return None

def extractIconData(html):
  icons = []

  # Extract the icon urls from the given site, ...
  links = extractIconLinks(html)

  # ... fetch for each icon the unicode char.
  for key, value in links.items():
    try:
      iconHtml = fetchSite(value)
      iconUnicode = extractUnicode(iconHtml)
      icons.append({'name': key, 'link': value, 'unicode': iconUnicode})
    except:
      print("Failed to fetch icon {} from {}".format(key, value))

  return icons

def main():
  # Prepare the url of the main site ...
  fawesomeUrl = "https://fortawesome.github.io/Font-Awesome/icons/"

  # ... fetch its' content ...
  fawesomeHtml = fetchSite(fawesomeUrl)

  # ... and extract the icon data.
  icons = extractIconData(fawesomeHtml)

  # Write the result to fontawesome.js.
  with open('fontawesome.js', 'w') as fp:
    line = '\t'
    fp.write("var Icon = {\n")
    for icon in icons:
      escapedName = icon['name'].replace('-', '_')
      iconEntry = '{}: "{}", '.format(escapedName, icon['unicode'])
      if len('{}{}'.format(line, iconEntry)) <= 80:
        line = '{}{}'.format(line, iconEntry)
      else:
        fp.write('{}\n'.format(line))
        line = '\t{}'.format(iconEntry)
    fp.write('{}\n}};'.format(line))

if __name__ == "__main__":
  main()

This will generate a file in the current working directory called fontawesome.js with the following content (shorted):

var Icon = {
    fa_copyright: "\uf1f9", fa_connectdevelop: "\uf20e", fa_archive: "\uf187",
    fa_taxi: "\uf1ba", fa_file_sound_o: "\uf1c7",
    ...
    fa_link: "\uf0c1",
};

The resulting javascript file could be loaded and accessed within the *.qml file as Mark described in his Blog Post:

import QtQuick 2.5

import "fontawesome.js" as FontAwesome

ApplicationWindow {
  visible: true
  width: 300
  height: 300
  title: qsTr("Font Awesome - Test")

  FontLoader {
    source: "fontawesome-webfont.ttf"
  }

  Rectangle {
    id: main
    anchors.fill: parent

    Text {
        anchors.horizontalCenter: main.horizontalCenter
        anchors.verticalCenter: main.verticalCenter
        font.pointSize: 100
        font.family: "FontAwesome"
        text: FontAwesome.Icon.fa_optin_monster
    }
  }
}

The above QML code should produce the following output:

Font Awesome Test Application

That’s it. Enjoy and until next time: Keep coding!


is a Computer Science MSc. interested in hardware hacking, embedded Linux, compilers, etc.