https://github.com/hluk/CopyQ/commit/f08c0d46a239362c5d3525ef9c3ba943bb00f734
https://bugs.gentoo.org/958277#c5

commit 7f1de919d2f6c3a84041d8f8afeff02a17290e16
Author: Lukas Holecek <hluk@email.cz>
Date:   Mon Apr 7 11:50:05 2025 +0200

    Fix QChar construction for Qt 6.9

diff --git a/plugins/itemencrypted/itemencrypted.cpp b/plugins/itemencrypted/itemencrypted.cpp
index 666dedde..73f47017 100644
--- a/plugins/itemencrypted/itemencrypted.cpp
+++ b/plugins/itemencrypted/itemencrypted.cpp
@@ -13,6 +13,7 @@
 #include "common/textdata.h"
 #include "gui/icons.h"
 #include "gui/iconwidget.h"
+#include "gui/fromiconid.h"
 #include "item/serialize.h"
 
 #ifdef HAS_TESTS
@@ -859,7 +860,7 @@ QVector<Command> ItemEncryptedLoader::commands() const
     Command c;
     c.internalId = QStringLiteral("copyq_encrypted_encrypt");
     c.name = ItemEncryptedLoader::tr("Encrypt (needs GnuPG)");
-    c.icon = QString(QChar(IconLock));
+    c.icon = fromIconId(IconLock);
     c.input = "!OUTPUT";
     c.output = mimeEncryptedData;
     c.inMenu = true;
@@ -870,7 +871,7 @@ QVector<Command> ItemEncryptedLoader::commands() const
     c = Command();
     c.internalId = QStringLiteral("copyq_encrypted_decrypt");
     c.name = ItemEncryptedLoader::tr("Decrypt");
-    c.icon = QString(QChar(IconUnlock));
+    c.icon = fromIconId(IconUnlock);
     c.input = mimeEncryptedData;
     c.output = mimeItems;
     c.inMenu = true;
@@ -881,7 +882,7 @@ QVector<Command> ItemEncryptedLoader::commands() const
     c = Command();
     c.internalId = QStringLiteral("copyq_encrypted_decrypt_and_copy");
     c.name = ItemEncryptedLoader::tr("Decrypt and Copy");
-    c.icon = QString(QChar(IconUnlockKeyhole));
+    c.icon = fromIconId(IconUnlockKeyhole);
     c.input = mimeEncryptedData;
     c.inMenu = true;
     c.cmd = "copyq: plugins.itemencrypted.copyEncryptedItems()";
@@ -891,7 +892,7 @@ QVector<Command> ItemEncryptedLoader::commands() const
     c = Command();
     c.internalId = QStringLiteral("copyq_encrypted_decrypt_and_paste");
     c.name = ItemEncryptedLoader::tr("Decrypt and Paste");
-    c.icon = QString(QChar(IconUnlockKeyhole));
+    c.icon = fromIconId(IconUnlockKeyhole);
     c.input = mimeEncryptedData;
     c.inMenu = true;
     c.cmd = "copyq: plugins.itemencrypted.pasteEncryptedItems()";
diff --git a/plugins/itemfakevim/fakevim/fakevimhandler.cpp b/plugins/itemfakevim/fakevim/fakevimhandler.cpp
index c28d2504..4205b1cc 100644
--- a/plugins/itemfakevim/fakevim/fakevimhandler.cpp
+++ b/plugins/itemfakevim/fakevim/fakevimhandler.cpp
@@ -1033,7 +1033,7 @@ QString quoteUnprintable(const QString &ba)
         else if (cc == '\n')
             res += "<CR>";
         else
-            res += QString("\\x%1").arg(c.unicode(), 2, 16, QLatin1Char('0'));
+            res += QString("\\x%1").arg(cc, 2, 16, QLatin1Char('0'));
     }
     return res;
 }
diff --git a/plugins/itempinned/itempinned.cpp b/plugins/itempinned/itempinned.cpp
index eb2518d1..19098149 100644
--- a/plugins/itempinned/itempinned.cpp
+++ b/plugins/itempinned/itempinned.cpp
@@ -5,6 +5,7 @@
 #include "common/command.h"
 #include "common/contenttype.h"
 #include "common/display.h"
+#include "gui/fromiconid.h"
 
 #ifdef HAS_TESTS
 #   include "tests/itempinnedtests.h"
@@ -32,7 +33,7 @@ bool isPinned(const QModelIndex &index)
 Command dummyPinCommand()
 {
     Command c;
-    c.icon = QString(QChar(IconThumbtack));
+    c.icon = fromIconId(IconThumbtack);
     c.inMenu = true;
     return c;
 }
diff --git a/plugins/itemsync/itemsync.cpp b/plugins/itemsync/itemsync.cpp
index 8d3466d7..77c73bea 100644
--- a/plugins/itemsync/itemsync.cpp
+++ b/plugins/itemsync/itemsync.cpp
@@ -15,6 +15,7 @@
 #include "gui/icons.h"
 #include "gui/iconfont.h"
 #include "gui/iconwidget.h"
+#include "gui/fromiconid.h"
 #include "item/itemfilter.h"
 
 #ifdef HAS_TESTS
@@ -100,7 +101,7 @@ void writeConfiguration(QIODevice *file, const QStringList &savedFiles)
 
 QString iconFromId(int id)
 {
-    return id != -1 ? QString(QChar(id)) : QString();
+    return id != -1 ? fromIconId(id) : QString();
 }
 
 QPushButton *createBrowseButton()
diff --git a/plugins/itemtags/itemtags.cpp b/plugins/itemtags/itemtags.cpp
index fe2a2f4c..d86dd908 100644
--- a/plugins/itemtags/itemtags.cpp
+++ b/plugins/itemtags/itemtags.cpp
@@ -10,6 +10,7 @@
 #include "common/textdata.h"
 #include "gui/iconfont.h"
 #include "gui/iconselectbutton.h"
+#include "gui/fromiconid.h"
 #include "gui/pixelratio.h"
 #include "item/itemfilter.h"
 
@@ -153,7 +154,7 @@ QString removeTagText()
 Command dummyTagCommand()
 {
     Command c;
-    c.icon = QString(QChar(IconTag));
+    c.icon = fromIconId(IconTag);
     c.inMenu = true;
     return c;
 }
diff --git a/src/common/globalshortcutcommands.cpp b/src/common/globalshortcutcommands.cpp
index 4bb8b756..d0b7eeeb 100644
--- a/src/common/globalshortcutcommands.cpp
+++ b/src/common/globalshortcutcommands.cpp
@@ -3,6 +3,7 @@
 #include "globalshortcutcommands.h"
 
 #include "common/command.h"
+#include "gui/fromiconid.h"
 
 #include <QCoreApplication>
 #include <QLocale>
@@ -50,7 +51,7 @@ Command createGlobalShortcut(const QString &name, const QString &script, IconId
     c.internalId = internalId;
     c.name = name;
     c.cmd = "copyq: " + script;
-    c.icon = QString(QChar(icon));
+    c.icon = fromIconId(icon);
     c.isGlobalShortcut = true;
     return c;
 }
diff --git a/src/common/predefinedcommands.cpp b/src/common/predefinedcommands.cpp
index 236755aa..08ab0ffb 100644
--- a/src/common/predefinedcommands.cpp
+++ b/src/common/predefinedcommands.cpp
@@ -8,6 +8,7 @@
 #include "common/shortcuts.h"
 #include "common/textdata.h"
 #include "gui/icons.h"
+#include "gui/fromiconid.h"
 #include "platform/platformnativeinterface.h"
 
 #include <QCoreApplication>
@@ -38,14 +39,14 @@ QVector<Command> predefinedCommands()
     commands.prepend(Command());
     c = &commands.first();
     c->name = AddCommandDialog::tr("New command");
-    c->icon = QString(QChar(IconFile));
+    c->icon = fromIconId(IconFile);
     c->input = c->output = QString();
     c->wait = c->automatic = c->remove = false;
     c->sep = QLatin1String("\\n");
 
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Ignore items with no or single character");
-    c->icon = QString(QChar(IconCircleExclamation));
+    c->icon = fromIconId(IconCircleExclamation);
     c->cmd  = R"(function hasEmptyOrSingleCharText() {
     if (dataFormats().includes(mimeText)) {
         var text = str(data(mimeText));
@@ -83,7 +84,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Open in &Browser");
     c->re   = reURL;
-    c->icon = QString(QChar(IconGlobe));
+    c->icon = fromIconId(IconGlobe);
     c->cmd  = QStringLiteral("copyq open %1");
     c->hideWindow = true;
     c->inMenu = true;
@@ -91,7 +92,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Paste as Plain Text");
     c->input = mimeText;
-    c->icon = QString(QChar(IconPaste));
+    c->icon = fromIconId(IconPaste);
     c->cmd  = QStringLiteral("copyq:") + pasteAsPlainTextScript("input()");
     c->hideWindow = true;
     c->inMenu = true;
@@ -99,7 +100,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Autoplay videos");
     c->re   = QRegularExpression("^http://.*\\.(mp4|avi|mkv|wmv|flv|ogv)$");
-    c->icon = QString(QChar(IconCirclePlay));
+    c->icon = fromIconId(IconCirclePlay);
     c->cmd  = QStringLiteral("copyq open %1");
     c->automatic = true;
     c->hideWindow = true;
@@ -108,13 +109,13 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Copy URL (web address) to other tab");
     c->re   = reURL;
-    c->icon = QString(QChar(IconCopy));
+    c->icon = fromIconId(IconCopy);
     c->tab  = QStringLiteral("&web");
     c->automatic = true;
 
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Create thumbnail (needs ImageMagick)");
-    c->icon = QString(QChar(IconImage));
+    c->icon = fromIconId(IconImage);
     c->cmd  = QStringLiteral("convert - -resize 92x92 png:-");
     c->input = QStringLiteral("image/png");
     c->output = QStringLiteral("image/png");
@@ -123,7 +124,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Create QR Code from URL (needs qrencode)");
     c->re   = reURL;
-    c->icon = QString(QChar(IconQrcode));
+    c->icon = fromIconId(IconQrcode);
     c->cmd  = QStringLiteral("qrencode -o - -t PNG -s 6");
     c->input = mimeText;
     c->output = QStringLiteral("image/png");
@@ -134,7 +135,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Add to %1 tab", "%1 is quoted Tasks tab name")
             .arg(todoTabQuoted);
-    c->icon = QString(QChar(IconShare));
+    c->icon = fromIconId(IconShare);
     c->tab  = todoTab;
     c->input = mimeText;
     c->inMenu = true;
@@ -142,7 +143,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Move to %1 tab", "%1 is quoted Tasks tab name")
             .arg(todoTabQuoted);
-    c->icon = QString(QChar(IconShare));
+    c->icon = fromIconId(IconShare);
     c->tab  = todoTab;
     c->remove = true;
     c->inMenu = true;
@@ -150,7 +151,7 @@ synchronizeToSelection = function() {
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Ignore copied files");
     c->re   = reNotURL;
-    c->icon = QString(QChar(IconCircleExclamation));
+    c->icon = fromIconId(IconCircleExclamation);
     c->input = mimeUriList;
     c->remove = true;
     c->automatic = true;
@@ -159,7 +160,7 @@ synchronizeToSelection = function() {
         c = newCommand(&commands);
         c->name = AddCommandDialog::tr("Ignore *\"Password\"* window");
         c->wndre = QRegularExpression(AddCommandDialog::tr("Password"));
-        c->icon = QString(QChar(IconAsterisk));
+        c->icon = fromIconId(IconAsterisk);
         c->remove = true;
         c->automatic = true;
         c->cmd = QStringLiteral("copyq ignore");
@@ -167,14 +168,14 @@ synchronizeToSelection = function() {
 
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Move to Trash");
-    c->icon = QString(QChar(IconTrash));
+    c->icon = fromIconId(IconTrash);
     c->inMenu = true;
     c->tab  = AddCommandDialog::tr("(trash)");
     c->remove = true;
 
     c = newCommand(&commands);
     c->name = AddCommandDialog::tr("Clear Current Tab");
-    c->icon = QString(QChar(IconBroom));
+    c->icon = fromIconId(IconBroom);
     c->inMenu = true;
     c->cmd = QStringLiteral("copyq: ItemSelection(selectedTab()).selectRemovable().removeAll()");
     c->matchCmd = QStringLiteral("copyq: tab(selectedTab()); if (size() == 0) fail()");
diff --git a/src/gui/commanddialog.cpp b/src/gui/commanddialog.cpp
index 2ac1355e..86dd29b1 100644
--- a/src/gui/commanddialog.cpp
+++ b/src/gui/commanddialog.cpp
@@ -13,6 +13,7 @@
 #include "gui/commandwidget.h"
 #include "gui/iconfactory.h"
 #include "gui/icons.h"
+#include "gui/fromiconid.h"
 #include "platform/platformclipboard.h"
 #include "platform/platformnativeinterface.h"
 
@@ -48,7 +49,7 @@ QIcon getCommandIcon(const QString &iconString, int commandType)
           : commandType & CommandType::Menu ? QColor(100,220,255)
           : QColor(255,100,100);
 
-    return iconFromFile(iconString, QString(QChar(icon)), color);
+    return iconFromFile(iconString, fromIconId(icon), color);
 }
 
 bool hasCommandsToPaste(const QString &text)
diff --git a/src/gui/fromiconid.h b/src/gui/fromiconid.h
new file mode 100644
index 00000000..e00104b2
--- /dev/null
+++ b/src/gui/fromiconid.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+#pragma once
+
+#include <QChar>
+#include <QString>
+
+inline QString fromIconId(int id) {
+    return QString(QChar(id));
+}
diff --git a/src/gui/iconfactory.cpp b/src/gui/iconfactory.cpp
index b0cfcf3b..df28a4f4 100644
--- a/src/gui/iconfactory.cpp
+++ b/src/gui/iconfactory.cpp
@@ -3,8 +3,8 @@
 #include "iconfactory.h"
 
 #include "gui/fix_icon_id.h"
-#include "gui/icons.h"
 #include "gui/iconfont.h"
+#include "gui/fromiconid.h"
 #include "gui/pixelratio.h"
 
 #include <QBitmap>
@@ -265,7 +265,7 @@ QPixmap drawFontIcon(ushort id, int w, int h, const QColor &color)
 
     // Center the icon to whole pixels so it stays sharp.
     const auto flags = Qt::AlignTop | Qt::AlignLeft;
-    const auto iconText = QString(QChar(id));
+    const auto iconText = fromIconId(id);
     auto boundingRect = painter.boundingRect(0, 0, w, h, flags, iconText);
     const auto x = w - boundingRect.width();
     // If icon is wider, assume that a tag will be rendered and align image to the right.
diff --git a/src/gui/iconselectbutton.cpp b/src/gui/iconselectbutton.cpp
index e26eaeff..4fc8c0fb 100644
--- a/src/gui/iconselectbutton.cpp
+++ b/src/gui/iconselectbutton.cpp
@@ -7,7 +7,7 @@
 #include "gui/fix_icon_id.h"
 #include "gui/iconfont.h"
 #include "gui/iconselectdialog.h"
-#include "gui/icons.h"
+#include "gui/fromiconid.h"
 
 #include <QApplication>
 #include <QIcon>
@@ -40,7 +40,7 @@ void IconSelectButton::setCurrentIcon(const QString &iconString)
     if ( iconString.size() == 1 ) {
         const QChar c = iconString[0];
         const ushort id = fixIconId( c.unicode() );
-        m_currentIcon = QString(QChar(id));
+        m_currentIcon = fromIconId(id);
         setFont(iconFont());
         setText(m_currentIcon);
     } else if ( !iconString.isEmpty() ) {
diff --git a/src/gui/notificationbasic.cpp b/src/gui/notificationbasic.cpp
index ed688f39..13a98528 100644
--- a/src/gui/notificationbasic.cpp
+++ b/src/gui/notificationbasic.cpp
@@ -8,7 +8,7 @@
 #include "common/textdata.h"
 #include "common/timer.h"
 #include "gui/iconfactory.h"
-#include "gui/icons.h"
+#include "gui/fromiconid.h"
 #include "gui/pixelratio.h"
 
 #include <QApplication>
@@ -230,7 +230,7 @@ void NotificationBasicWidget::setIcon(const QString &icon)
 
 void NotificationBasicWidget::setIcon(ushort icon)
 {
-    m_icon = QString(QChar(icon));
+    m_icon = fromIconId(icon);
 }
 
 void NotificationBasicWidget::setInterval(int msec)
diff --git a/src/scriptable/scriptable.cpp b/src/scriptable/scriptable.cpp
index 8893140c..7d5fd294 100644
--- a/src/scriptable/scriptable.cpp
+++ b/src/scriptable/scriptable.cpp
@@ -14,6 +14,7 @@
 #include "common/textdata.h"
 #include "gui/clipboardspy.h"
 #include "gui/icons.h"
+#include "gui/fromiconid.h"
 #include "item/itemfactory.h"
 #include "item/serialize.h"
 #include "platform/platformclipboard.h"
@@ -2912,7 +2913,7 @@ void Scriptable::showExceptionMessage(const QString &message)
     QtPrivate::QHashCombine hash;
     const auto id = hash(hash(0, title), message);
     const auto notificationId = QString::number(id);
-    m_proxy->showMessage(title, message, QString(QChar(IconCircleExclamation)), 8000, notificationId);
+    m_proxy->showMessage(title, message, fromIconId(IconCircleExclamation), 8000, notificationId);
 }
 
 QVector<int> Scriptable::getRows() const

