support as much emojis as possible for Qt < 6.9.0

This commit is contained in:
Gaelle Braud 2026-02-16 15:22:47 +01:00
parent 7c3bed2bcb
commit a5cb280c82
13 changed files with 58 additions and 13 deletions

View file

@ -98,6 +98,8 @@ endif()
if(${Qt6_VERSION} VERSION_LESS "6.8.0")
message( FATAL_ERROR "Linphone requires Qt 6.8.0 or newer. Exiting CMake." )
elseif(${Qt6_VERSION} VERSION_LESS "6.9.0")
message(WARNING "Using Qt version "${Qt6_VERSION} ". Some emojis could not be rendered well as Linphone requires Qt 6.9.0 minimum version for rendering them without safety issue.")
endif()
qt6_standard_project_setup()

View file

@ -545,7 +545,13 @@ QStringList ChatMessageCore::getReactionsSingletonAsStrings() const {
auto map = reac.toMap();
auto count = map["count"].toInt();
totalCount += count;
QString body = map["body"].toString();
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
reacStringList.append(
ToolModel::encodeTextToQmlRichFormat(QString("%1 %2").arg(map["body"].toString()).arg(count)));
#else
reacStringList.append(QString("%1 %2").arg(map["body"].toString()).arg(count));
#endif
}
reacStringList.prepend(QString("%1 %2").arg(mTotalReactionsLabel).arg(totalCount));
return reacStringList;

View file

@ -124,7 +124,7 @@ inline std::string u32_to_ascii(std::u32string const &s) {
return out;
}
QString Utils::getInitials(const QString &username) {
QString Utils::getInitials(const QString &username, int letterCount) {
if (username.isEmpty()) return "";
QRegularExpression regex("[\\s\\.]+");
@ -136,7 +136,13 @@ QString Utils::getInitials(const QString &username) {
// if name starts by an emoji, only return this one
QVector<uint> utf32_string = username.toUcs4();
auto code = utf32_string[0];
if (Utils::codepointIsEmoji(code)) return QString::fromStdU32String(char32);
if (Utils::codepointIsEmoji(code)) {
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
return Utils::encodeEmojiToQmlRichFormat(QString::fromStdU32String(char32));
#else
QString::fromStdU32String(char32);
#endif
}
QStringList initials;
initials << QString::fromStdU32String(char32);
@ -145,6 +151,7 @@ QString Utils::getInitials(const QString &username) {
str32 = words[i].toStdU32String();
char32[0] = str32[0];
initials << QString::fromStdU32String(char32);
if (initials.count() >= letterCount) break;
std::string converted = u32_to_ascii(char32);
if (Utils::codepointIsEmoji(atoi(converted.c_str()))) {
break;
@ -1894,7 +1901,7 @@ VariantObject *Utils::encodeTextToQmlRichFormat(const QString &text,
QString Utils::encodeEmojiToQmlRichFormat(const QString &body) {
QString fmtBody = "";
QVector<uint> utf32_string = body.toUcs4();
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
bool insideFontBlock = false;
for (auto &code : utf32_string) {
if (Utils::codepointIsEmoji(code)) {
@ -1914,6 +1921,9 @@ QString Utils::encodeEmojiToQmlRichFormat(const QString &body) {
if (insideFontBlock) {
fmtBody += "</font>";
}
#else
fmtBody = body;
#endif
return fmtBody;
}

View file

@ -65,7 +65,7 @@ public:
Q_INVOKABLE static QString getUsername(const QString &address);
Q_INVOKABLE static QString getGivenNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
Q_INVOKABLE static QString getInitials(const QString &username, int letterCount = 2); // Support UTF32
Q_INVOKABLE static VariantObject *findLocalAccountByAddress(const QString &address);
Q_INVOKABLE static void

View file

@ -103,6 +103,7 @@ Control.TabBar {
contentItem: Text {
id: tabText
width: implicitWidth
textFormat: Text.RichText
font {
pixelSize: mainItem.pixelSize
weight: mainItem.textWeight

View file

@ -180,7 +180,8 @@ ListView {
id: friendAddress
Layout.fillWidth: true
maximumLineCount: 1
text: modelData? modelData.core.title : ""
text: modelData? UtilsCpp.encodeEmojiToQmlRichFormat(modelData.core.title) : ""
textFormat: Text.RichText
color: DefaultStyle.main2_800
font {
pixelSize: Typography.p1.pixelSize

View file

@ -536,6 +536,7 @@ Control.Control {
model: ConstantsCpp.reactionsList
delegate: Button {
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData)
textFormat: Text.RichText
background: Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_200

View file

@ -157,6 +157,7 @@ Loader{
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: initialItem.initials
textFormat: Text.RichText
font {
pixelSize: initialItem.height * 36 / 120
weight: Typography.h4.weight

View file

@ -36,7 +36,7 @@ FocusScope {
property real itemsRightMargin: Utils.getSizeWithScreenRatio(39)
property var displayName: searchResultItem? searchResultItem.core.fullName : ""
property var initial: displayName.length > 0 ? displayName[0].toLocaleLowerCase(AppCpp.localeAsString) : ''
property var initial: displayName.length > 0 ? UtilsCpp.getInitials(displayName, 1).toLocaleLowerCase(AppCpp.localeAsString) : ''
signal clicked(var mouse)
signal contactDeletionRequested(FriendGui contact)
@ -45,7 +45,7 @@ FocusScope {
MouseArea {
Text {
id: initial
id: initialText
anchors.left: parent.left
visible: mainItem.showInitials
anchors.verticalCenter: parent.verticalCenter
@ -53,7 +53,8 @@ FocusScope {
verticalAlignment: Text.AlignVCenter
width: Utils.getSizeWithScreenRatio(20)
opacity: previousInitial != mainItem.initial ? 1 : 0
text: mainItem.initial || ""
text: mainItem.initial
textFormat: Text.RichText
color: DefaultStyle.main2_400
font {
pixelSize: Utils.getSizeWithScreenRatio(20)
@ -63,7 +64,7 @@ FocusScope {
}
RowLayout {
id: contactDelegate
anchors.left: initial.visible ? initial.right : parent.left
anchors.left: initialText.visible ? initialText.right : parent.left
anchors.right: parent.right
anchors.rightMargin: mainItem.itemsRightMargin
anchors.top: parent.top
@ -84,8 +85,9 @@ FocusScope {
visible: mainItem.showDisplayName
Layout.fillWidth: true
Layout.preferredHeight: visible ? implicitHeight: 0
text: UtilsCpp.boldTextPart(mainItem.displayName,
text: UtilsCpp.boldTextPart(UtilsCpp.encodeEmojiToQmlRichFormat((mainItem.displayName)),
mainItem.highlightText)
textFormat: Text.RichText
font {
pixelSize: mainItem.showDefaultAddress ? Typography.h4.pixelSize : Typography.p1.pixelSize
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase

View file

@ -108,9 +108,10 @@ FocusScope {
}
ColumnLayout {
Text {
text: mainItem.chat?.core.title || ""
text: UtilsCpp.encodeEmojiToQmlRichFormat(mainItem.chat?.core.title) || ""
color: DefaultStyle.main2_600
maximumLineCount: 1
textFormat: Text.RichText
font {
pixelSize: Typography.h4.pixelSize
weight: Utils.getSizeWithScreenRatio(400)

View file

@ -89,6 +89,18 @@ ColumnLayout {
Layout.preferredHeight: title.contentHeight
anchors.margins: Utils.getSizeWithScreenRatio(2)
Text {
anchors.fill: parent
anchors.margins: 6
visible: !titleMainItem.isEditingSubject
text: UtilsCpp.encodeEmojiToQmlRichFormat(mainItem.chatGui.core.title) || ""
textFormat: Text.RichText
color: DefaultStyle.main2_700
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: Typography.p1
}
TextEdit {
id: title
anchors.fill: parent
@ -96,6 +108,7 @@ ColumnLayout {
font: Typography.p1
color: DefaultStyle.main2_700
text: mainItem.chatGui.core.title || ""
visible: titleMainItem.isEditingSubject
enabled: titleMainItem.isEditingSubject
wrapMode: TextEdit.Wrap
horizontalAlignment: Text.AlignHCenter
@ -105,6 +118,11 @@ ColumnLayout {
titleMainItem.saveSubject()
titleMainItem.isEditingSubject = !titleMainItem.isEditingSubject
}
Keys.onEnterPressed: {
if (titleMainItem.isEditingSubject)
titleMainItem.saveSubject()
titleMainItem.isEditingSubject = !titleMainItem.isEditingSubject
}
}
}

View file

@ -64,6 +64,7 @@ MessageInfosLayout {
Item{Layout.fillWidth: true}
Text {
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData.body)
textFormat: Text.RichText
font {
pixelSize: Typography.h3.pixelSize
weight: Typography.p3.weight

View file

@ -55,10 +55,10 @@ AbstractMainPage {
}
}
onSelectedContactChanged: {
console.log("selected contact changed, go to contact details")
// if we are editing a contact, force staying on edition page
if (!rightPanelStackView.currentItem
|| rightPanelStackView.currentItem.objectName != "contactEdition") {
console.log("selected contact changed, go to contact details")
goToContactDetails()
}
}
@ -435,7 +435,8 @@ AbstractMainPage {
ColumnLayout {
spacing: 0
Text {
text: contactDetail.contactName
text: UtilsCpp.encodeEmojiToQmlRichFormat(contactDetail.contactName)
textFormat: Text.RichText
Layout.fillWidth: true
maximumLineCount: 1
font {