mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-04-17 20:08:28 +00:00
support as much emojis as possible for Qt < 6.9.0
This commit is contained in:
parent
7c3bed2bcb
commit
a5cb280c82
13 changed files with 58 additions and 13 deletions
|
|
@ -98,6 +98,8 @@ endif()
|
||||||
|
|
||||||
if(${Qt6_VERSION} VERSION_LESS "6.8.0")
|
if(${Qt6_VERSION} VERSION_LESS "6.8.0")
|
||||||
message( FATAL_ERROR "Linphone requires Qt 6.8.0 or newer. Exiting CMake." )
|
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()
|
endif()
|
||||||
|
|
||||||
qt6_standard_project_setup()
|
qt6_standard_project_setup()
|
||||||
|
|
|
||||||
|
|
@ -545,7 +545,13 @@ QStringList ChatMessageCore::getReactionsSingletonAsStrings() const {
|
||||||
auto map = reac.toMap();
|
auto map = reac.toMap();
|
||||||
auto count = map["count"].toInt();
|
auto count = map["count"].toInt();
|
||||||
totalCount += count;
|
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));
|
reacStringList.append(QString("%1 %2").arg(map["body"].toString()).arg(count));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
reacStringList.prepend(QString("%1 %2").arg(mTotalReactionsLabel).arg(totalCount));
|
reacStringList.prepend(QString("%1 %2").arg(mTotalReactionsLabel).arg(totalCount));
|
||||||
return reacStringList;
|
return reacStringList;
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ inline std::string u32_to_ascii(std::u32string const &s) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Utils::getInitials(const QString &username) {
|
QString Utils::getInitials(const QString &username, int letterCount) {
|
||||||
if (username.isEmpty()) return "";
|
if (username.isEmpty()) return "";
|
||||||
|
|
||||||
QRegularExpression regex("[\\s\\.]+");
|
QRegularExpression regex("[\\s\\.]+");
|
||||||
|
|
@ -136,7 +136,13 @@ QString Utils::getInitials(const QString &username) {
|
||||||
// if name starts by an emoji, only return this one
|
// if name starts by an emoji, only return this one
|
||||||
QVector<uint> utf32_string = username.toUcs4();
|
QVector<uint> utf32_string = username.toUcs4();
|
||||||
auto code = utf32_string[0];
|
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;
|
QStringList initials;
|
||||||
initials << QString::fromStdU32String(char32);
|
initials << QString::fromStdU32String(char32);
|
||||||
|
|
@ -145,6 +151,7 @@ QString Utils::getInitials(const QString &username) {
|
||||||
str32 = words[i].toStdU32String();
|
str32 = words[i].toStdU32String();
|
||||||
char32[0] = str32[0];
|
char32[0] = str32[0];
|
||||||
initials << QString::fromStdU32String(char32);
|
initials << QString::fromStdU32String(char32);
|
||||||
|
if (initials.count() >= letterCount) break;
|
||||||
std::string converted = u32_to_ascii(char32);
|
std::string converted = u32_to_ascii(char32);
|
||||||
if (Utils::codepointIsEmoji(atoi(converted.c_str()))) {
|
if (Utils::codepointIsEmoji(atoi(converted.c_str()))) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -1894,7 +1901,7 @@ VariantObject *Utils::encodeTextToQmlRichFormat(const QString &text,
|
||||||
QString Utils::encodeEmojiToQmlRichFormat(const QString &body) {
|
QString Utils::encodeEmojiToQmlRichFormat(const QString &body) {
|
||||||
QString fmtBody = "";
|
QString fmtBody = "";
|
||||||
QVector<uint> utf32_string = body.toUcs4();
|
QVector<uint> utf32_string = body.toUcs4();
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
|
||||||
bool insideFontBlock = false;
|
bool insideFontBlock = false;
|
||||||
for (auto &code : utf32_string) {
|
for (auto &code : utf32_string) {
|
||||||
if (Utils::codepointIsEmoji(code)) {
|
if (Utils::codepointIsEmoji(code)) {
|
||||||
|
|
@ -1914,6 +1921,9 @@ QString Utils::encodeEmojiToQmlRichFormat(const QString &body) {
|
||||||
if (insideFontBlock) {
|
if (insideFontBlock) {
|
||||||
fmtBody += "</font>";
|
fmtBody += "</font>";
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
fmtBody = body;
|
||||||
|
#endif
|
||||||
return fmtBody;
|
return fmtBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ public:
|
||||||
Q_INVOKABLE static QString getUsername(const QString &address);
|
Q_INVOKABLE static QString getUsername(const QString &address);
|
||||||
Q_INVOKABLE static QString getGivenNameFromFullName(const QString &fullName);
|
Q_INVOKABLE static QString getGivenNameFromFullName(const QString &fullName);
|
||||||
Q_INVOKABLE static QString getFamilyNameFromFullName(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 VariantObject *findLocalAccountByAddress(const QString &address);
|
||||||
|
|
||||||
Q_INVOKABLE static void
|
Q_INVOKABLE static void
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ Control.TabBar {
|
||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
id: tabText
|
id: tabText
|
||||||
width: implicitWidth
|
width: implicitWidth
|
||||||
|
textFormat: Text.RichText
|
||||||
font {
|
font {
|
||||||
pixelSize: mainItem.pixelSize
|
pixelSize: mainItem.pixelSize
|
||||||
weight: mainItem.textWeight
|
weight: mainItem.textWeight
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,8 @@ ListView {
|
||||||
id: friendAddress
|
id: friendAddress
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
text: modelData? modelData.core.title : ""
|
text: modelData? UtilsCpp.encodeEmojiToQmlRichFormat(modelData.core.title) : ""
|
||||||
|
textFormat: Text.RichText
|
||||||
color: DefaultStyle.main2_800
|
color: DefaultStyle.main2_800
|
||||||
font {
|
font {
|
||||||
pixelSize: Typography.p1.pixelSize
|
pixelSize: Typography.p1.pixelSize
|
||||||
|
|
|
||||||
|
|
@ -536,6 +536,7 @@ Control.Control {
|
||||||
model: ConstantsCpp.reactionsList
|
model: ConstantsCpp.reactionsList
|
||||||
delegate: Button {
|
delegate: Button {
|
||||||
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData)
|
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData)
|
||||||
|
textFormat: Text.RichText
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: DefaultStyle.grey_200
|
color: DefaultStyle.grey_200
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,7 @@ Loader{
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: initialItem.initials
|
text: initialItem.initials
|
||||||
|
textFormat: Text.RichText
|
||||||
font {
|
font {
|
||||||
pixelSize: initialItem.height * 36 / 120
|
pixelSize: initialItem.height * 36 / 120
|
||||||
weight: Typography.h4.weight
|
weight: Typography.h4.weight
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ FocusScope {
|
||||||
property real itemsRightMargin: Utils.getSizeWithScreenRatio(39)
|
property real itemsRightMargin: Utils.getSizeWithScreenRatio(39)
|
||||||
|
|
||||||
property var displayName: searchResultItem? searchResultItem.core.fullName : ""
|
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 clicked(var mouse)
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
|
|
@ -45,7 +45,7 @@ FocusScope {
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
Text {
|
Text {
|
||||||
id: initial
|
id: initialText
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
visible: mainItem.showInitials
|
visible: mainItem.showInitials
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
@ -53,7 +53,8 @@ FocusScope {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
width: Utils.getSizeWithScreenRatio(20)
|
width: Utils.getSizeWithScreenRatio(20)
|
||||||
opacity: previousInitial != mainItem.initial ? 1 : 0
|
opacity: previousInitial != mainItem.initial ? 1 : 0
|
||||||
text: mainItem.initial || ""
|
text: mainItem.initial
|
||||||
|
textFormat: Text.RichText
|
||||||
color: DefaultStyle.main2_400
|
color: DefaultStyle.main2_400
|
||||||
font {
|
font {
|
||||||
pixelSize: Utils.getSizeWithScreenRatio(20)
|
pixelSize: Utils.getSizeWithScreenRatio(20)
|
||||||
|
|
@ -63,7 +64,7 @@ FocusScope {
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: contactDelegate
|
id: contactDelegate
|
||||||
anchors.left: initial.visible ? initial.right : parent.left
|
anchors.left: initialText.visible ? initialText.right : parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: mainItem.itemsRightMargin
|
anchors.rightMargin: mainItem.itemsRightMargin
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
@ -84,8 +85,9 @@ FocusScope {
|
||||||
visible: mainItem.showDisplayName
|
visible: mainItem.showDisplayName
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: visible ? implicitHeight: 0
|
Layout.preferredHeight: visible ? implicitHeight: 0
|
||||||
text: UtilsCpp.boldTextPart(mainItem.displayName,
|
text: UtilsCpp.boldTextPart(UtilsCpp.encodeEmojiToQmlRichFormat((mainItem.displayName)),
|
||||||
mainItem.highlightText)
|
mainItem.highlightText)
|
||||||
|
textFormat: Text.RichText
|
||||||
font {
|
font {
|
||||||
pixelSize: mainItem.showDefaultAddress ? Typography.h4.pixelSize : Typography.p1.pixelSize
|
pixelSize: mainItem.showDefaultAddress ? Typography.h4.pixelSize : Typography.p1.pixelSize
|
||||||
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
|
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,10 @@ FocusScope {
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Text {
|
Text {
|
||||||
text: mainItem.chat?.core.title || ""
|
text: UtilsCpp.encodeEmojiToQmlRichFormat(mainItem.chat?.core.title) || ""
|
||||||
color: DefaultStyle.main2_600
|
color: DefaultStyle.main2_600
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
|
textFormat: Text.RichText
|
||||||
font {
|
font {
|
||||||
pixelSize: Typography.h4.pixelSize
|
pixelSize: Typography.h4.pixelSize
|
||||||
weight: Utils.getSizeWithScreenRatio(400)
|
weight: Utils.getSizeWithScreenRatio(400)
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,18 @@ ColumnLayout {
|
||||||
Layout.preferredHeight: title.contentHeight
|
Layout.preferredHeight: title.contentHeight
|
||||||
anchors.margins: Utils.getSizeWithScreenRatio(2)
|
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 {
|
TextEdit {
|
||||||
id: title
|
id: title
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -96,6 +108,7 @@ ColumnLayout {
|
||||||
font: Typography.p1
|
font: Typography.p1
|
||||||
color: DefaultStyle.main2_700
|
color: DefaultStyle.main2_700
|
||||||
text: mainItem.chatGui.core.title || ""
|
text: mainItem.chatGui.core.title || ""
|
||||||
|
visible: titleMainItem.isEditingSubject
|
||||||
enabled: titleMainItem.isEditingSubject
|
enabled: titleMainItem.isEditingSubject
|
||||||
wrapMode: TextEdit.Wrap
|
wrapMode: TextEdit.Wrap
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
@ -105,6 +118,11 @@ ColumnLayout {
|
||||||
titleMainItem.saveSubject()
|
titleMainItem.saveSubject()
|
||||||
titleMainItem.isEditingSubject = !titleMainItem.isEditingSubject
|
titleMainItem.isEditingSubject = !titleMainItem.isEditingSubject
|
||||||
}
|
}
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
if (titleMainItem.isEditingSubject)
|
||||||
|
titleMainItem.saveSubject()
|
||||||
|
titleMainItem.isEditingSubject = !titleMainItem.isEditingSubject
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ MessageInfosLayout {
|
||||||
Item{Layout.fillWidth: true}
|
Item{Layout.fillWidth: true}
|
||||||
Text {
|
Text {
|
||||||
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData.body)
|
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData.body)
|
||||||
|
textFormat: Text.RichText
|
||||||
font {
|
font {
|
||||||
pixelSize: Typography.h3.pixelSize
|
pixelSize: Typography.h3.pixelSize
|
||||||
weight: Typography.p3.weight
|
weight: Typography.p3.weight
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ AbstractMainPage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSelectedContactChanged: {
|
onSelectedContactChanged: {
|
||||||
console.log("selected contact changed, go to contact details")
|
|
||||||
// if we are editing a contact, force staying on edition page
|
// if we are editing a contact, force staying on edition page
|
||||||
if (!rightPanelStackView.currentItem
|
if (!rightPanelStackView.currentItem
|
||||||
|| rightPanelStackView.currentItem.objectName != "contactEdition") {
|
|| rightPanelStackView.currentItem.objectName != "contactEdition") {
|
||||||
|
console.log("selected contact changed, go to contact details")
|
||||||
goToContactDetails()
|
goToContactDetails()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -435,7 +435,8 @@ AbstractMainPage {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Text {
|
Text {
|
||||||
text: contactDetail.contactName
|
text: UtilsCpp.encodeEmojiToQmlRichFormat(contactDetail.contactName)
|
||||||
|
textFormat: Text.RichText
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
font {
|
font {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue