Skip to content

Instantly share code, notes, and snippets.

@fizzyade
Last active February 18, 2020 23:01
Show Gist options
  • Save fizzyade/3661fea2da280db211d4dd27db01aa60 to your computer and use it in GitHub Desktop.
Save fizzyade/3661fea2da280db211d4dd27db01aa60 to your computer and use it in GitHub Desktop.
QString (Qt) utility to allow strings to use Font Awesome icons alongside regular text easily.

Glyphs in Rich Text

Here's a small utility class that uses a simple markup extension to easily allow you to use Font Awesome glyphs in rich text on Qt. This allows widgets such as QLabel to use glyphs from the excellent Font Awesome font.

You will need:

Loading the font

The class is designed to embed Font Awesome in the application binary. You should set the file locations appropriately in the class.

QFontDatabase::addApplicationFont(":/FontAwesome/Free-Regular.otf");
QFontDatabase::addApplicationFont(":/FontAwesome/Free-Solid.otf");`
QFontDatabase::addApplicationFont(":/FontAwesome/Free-Brands.otf");`

Additionally, if you supply the _variables.scss file (available on github, the class will parse this and you will be able to use the "fa-" style names to refer to glyphs rather than unicode numbers.

(Adjust the file locations as necessary)

Ensuring the target is set to Rich Text mode

Ensure that the Widget you want to use the font on is set to rich text mode:

myWidget->setTextFormat(Qt::RichText);

Using the glyphs

Simply pass the string you want to display into the function FAString::getString, it accepts a markup inside it of the following syntax:

[far xxxx] [far fa-<glpyh name>] [fas xxxx] [fas fa-<glpyh name>] [fab xxxx] [fab fa-<glpyh name>]

Where far specifies the regular font, fas is the strong font and fab is the brands font. you will need to select the correct font according the the character you wish to use, this is displayed on the Font Awesome page when looking at a glyph

If you have supplied and loaded the _variables.scss file, then you will be able to use the names as displayed on the website to refer to the icons.

myWidget->setText(FAString::richText("[fas f2f2] 43s"));
myWidget->setText(FAString::richText("[fas fa-stopwatch] 43s"));

Will display a stopwatch icon followed by the text 43s.

That's it!

(For even more convenience you could subclass QLabel (for example as FALabel) and override the setText method to automatically call the FAString::richText function)


// FAString.h
//
// Copyright (c) 2019 Adrian Carpenter
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

class FAString
{
    private:
        static FAString *getInstance()
        {
            static auto instance = new FAString();

            return(instance);
        }

        FAString()
        {
            m_regularId = QFontDatabase::addApplicationFont(":/FontAwesome/Free-Regular.otf");
            m_solidId = QFontDatabase::addApplicationFont(":/FontAwesome/Free-Solid.otf");
            m_brandsId = QFontDatabase::addApplicationFont(":/FontAwesome/Free-Brands.otf");

            if (QFontDatabase::applicationFontFamilies(m_regularId).count())
                m_regularName = QFontDatabase::applicationFontFamilies(m_regularId).at(0);

            if (QFontDatabase::applicationFontFamilies(m_solidId).count())
                m_solidName = QFontDatabase::applicationFontFamilies(m_solidId).at(0);
                
            if (QFontDatabase::applicationFontFamilies(m_brandsId).count())
                m_brandsName = QFontDatabase::applicationFontFamilies(m_brandsId).at(0);

            QFile scssFile(":/FontAwesome/_variables.scss");

            if (scssFile.open(QFile::ReadOnly)) {
                auto scssContent = QString::fromUtf8(scssFile.readAll());

                if (!scssContent.isEmpty()) {
                    auto scssExpression = QRegularExpression(R"(\$fa-var-(?<name>.*)\:\W\\(?<code>([0-9]|[a-f]|[A-F]){1,4});)");

                    auto scssMatchIterator = scssExpression.globalMatch(scssContent);

                    while(scssMatchIterator.hasNext()) {
                        auto scssMatch = scssMatchIterator.next();

                        auto capturedTexts = scssMatch.capturedTexts();

                        if (capturedTexts.count()>=2) {
                            m_glyphMap["fa-"+capturedTexts.at(1)] = capturedTexts.at(2);
                        }
                    }
                }
            }

            m_styleString = QString(R"(
                <style>
                    .fas {
                        font-family:'%1';
                        font-weight:900
                    }

                    .far {
                        font-family:'%2';
                        font-weight:400
                    }
                    
                    .fab {
                        font-family:'%3';
                        font-weight:400
                    }

                    .body {
                        position: absolute;
                        top: 50%;
                    }
                </style>
            )").arg(m_regularName, m_solidName, m_brandsName);
        }

    public:

        static QString regularName()
        {
            return(getInstance()->m_regularName);
        }

        static QString solidName()
        {
            return(getInstance()->m_solidName);
        }
        
        static QString brandsName()
        {
            return(getInstance()->m_brandsName);
        }
        
        static QString richText(QString string)
        {
            auto expression = QRegularExpression(R"(\[(far|fas|fab) (([a-z]|\-|[0-9])*)\])");
            auto match = QRegularExpressionMatch();
            auto searchIndex = 0;

            while(string.indexOf(expression, searchIndex, &match)>=0) {
                if (match.capturedTexts().count()==4) {
                    auto richTextString = QString();
                    auto iconFont = match.capturedTexts().at(1);
                    auto iconId = match.capturedTexts().at(2);
                    auto iconCode = QString();

                    if (getInstance()->m_glyphMap.contains(iconId)) {
                        iconCode = getInstance()->m_glyphMap[iconId];
                    } else {
                        if ( (iconId.size()>=1) && ((iconId.size()<=4)) ) {
                            bool ok = false;

                            iconId.toInt(&ok, 16);

                            if (ok) {
                                iconCode = iconId;
                            }
                        }
                    }

                    if (iconCode.isNull()) {
                        richTextString = QString("");
                    } else {
                        richTextString = QString(R"(<span class="%1">&#x%2;</span>)").arg(iconFont, iconCode);
                    }

                    string.replace(match.capturedTexts().at(0), richTextString);
                } else {
                    searchIndex += match.captured().length();
                }
            }

            return(QString("<html>%1<body>%2</body></html>").arg(getInstance()->m_styleString).arg(string));
        }

    private:
        int m_regularId;
        int m_solidId;
        int m_brandsId;

        QString m_regularName;
        QString m_solidName;
        QString m_brandsName;

        QString m_styleString;

        QMap<QString, QString> m_glyphMap;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment