[SOLVED] QSystemTrayIcon notification message with custom icon

Issue

QSystemTrayIcon has a function :

void showMessage(const QString &title, const QString &msg,
                     MessageIcon icon = Information, int msecs = 10000);

is there a way to change it to custom icon , for example like this –

void showIconMessage(const QString &title, const QString &msg,
                     QIcon icon = QIcon(), int msecs = 10000);

without modifying the Qt sources

I know that showMessage (d is instance of QSystemTrayIconPrivate and is called with Q_D(QSystemTrayIcon) macro)

void QSystemTrayIcon::showMessage(const QString& title, const QString& msg,
                            QSystemTrayIcon::MessageIcon icon, int msecs)
{
    Q_D(QSystemTrayIcon);
    if (d->visible)
        d->showMessage_sys(title, msg, icon, msecs);
}

calls showMessage_sys from QSystemTrayIconPrivate where in turn all the magic with icon happens:

void QSystemTrayIconPrivate::showMessage_sys(const QString &message,
                                             const QString &title,
                                             QSystemTrayIcon::MessageIcon icon,
                                             int msecs)
{
    if (!qpa_sys)
        return;

    QIcon notificationIcon;
    switch (icon) {
    case QSystemTrayIcon::Information:
        notificationIcon = QApplication::style()-   >standardIcon(QStyle::SP_MessageBoxInformation);
        break;
    case QSystemTrayIcon::Warning:
        notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
        break;
    case QSystemTrayIcon::Critical:
        notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
        break;
    default:
        break;
    }
    qpa_sys->showMessage(message, title, notificationIcon,
                     static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
}

Now, it seems, that I need to re-implement these two functions in two classes and i’m ready to go, but.. It seems that QSystemTrayIcon is closely tied to QSystemTrayIconPrivate. Instance of QSystemTrayIconPrivate is created only in QSystemTrayIcon constructor (which I can’t really change if I plan to create classes that inherit both QSystemTrayIcon and QSystemTrayIconPrivate and re-implement showMessage functions):

QSystemTrayIcon::QSystemTrayIcon(QObject *parent)
: QObject(*new QSystemTrayIconPrivate(), parent)
{
}

QSystemTrayIcon::QSystemTrayIcon(const QIcon &icon, QObject *parent)
: QObject(*new QSystemTrayIconPrivate(), parent)
{
    setIcon(icon);
}

So is there anything I am missing? Or is there another way to simply show notification message with custom icon?

Solution

What you could try (not sure if it will work for system tray) is do the same as described in this answer and override the SP_MessageBoxWarning / SP_MessageBoxCritical / SP_MessageBoxInformation icons, but as I said I’m not sure if the system tray just uses a downscaled version of the message box icons or if the system tray icons are separate. In the case of the latter, I guess you will have to patch QT sources, maybe add a new item to the QSystemTrayIcon and patch the switch to call some function provided by you to return the needed icon. Something like:

void QSystemTrayIconPrivate::showMessage_sys(const QString &message,
                                             const QString &title,
                                             QSystemTrayIcon::MessageIcon icon,
                                             int msecs)
{
    if (!qpa_sys)
        return;

    QIcon notificationIcon;
    switch (icon) {
    case QSystemTrayIcon::Information:
        notificationIcon = QApplication::style()-   >standardIcon(QStyle::SP_MessageBoxInformation);
        break;
    case QSystemTrayIcon::Warning:
        notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
        break;
    case QSystemTrayIcon::Critical:
        notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
        break;
    case QSystemTrayIcon::Custom:
        // Call a function that will fetch the needed icon and assign it to notificationIcon
        break;
    default:
        break;
    }
    qpa_sys->showMessage(message, title, notificationIcon,
                     static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
}

Answered By – Rudolfs Bundulis

Answer Checked By – Terry (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *