mirror of https://github.com/qt/qtbase.git
uic/Python: Handle surrogates correctly
When a QString has surrogates (2 consecutive QChar's in UTF-16), convert to UCS4 first. Rewrite the formatStringSequence() helper (which operates on sequences of char/QChar) and related helpers to operate on uint instead of ushort and remove the non-type template parameter specifying the encoding by introducing a characterCode() converter helper to convert to uint. Check the QString passed in for surrogates and convert to UCS-4 if they are found (using the 32bit \U escape marker for Python). Pick-to: 6.10 6.9 6.8 Fixes: PYSIDE-3173 Change-Id: Ie1d1282d78ad80894cf67dd47ea6a332d7dfda25 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
This commit is contained in:
parent
992e4d89eb
commit
a50f38b630
|
@ -6,6 +6,8 @@
|
|||
#include <QtCore/qtextstream.h>
|
||||
#include <QtCore/QList>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace language {
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
@ -182,7 +184,7 @@ QLatin1StringView paletteColorRole(int v)
|
|||
// Helpers for formatting a character sequences
|
||||
|
||||
// Format a special character like '\x0a'
|
||||
static int formatEscapedNumber(QTextStream &str, ushort value, int base, int width,
|
||||
static int formatEscapedNumber(QTextStream &str, uint value, int base, int width,
|
||||
char prefix = 0)
|
||||
{
|
||||
int length = 1 + width;
|
||||
|
@ -236,24 +238,23 @@ static int formatSpecialCharacter(QTextStream &str, ushort value)
|
|||
|
||||
enum : int { maxSegmentSize = 1024 };
|
||||
|
||||
template <Encoding e>
|
||||
struct FormattingTraits
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct FormattingTraits<Encoding::Utf8>
|
||||
static uint characterCode(char c)
|
||||
{
|
||||
static ushort code(char c) { return uchar(c); }
|
||||
};
|
||||
return uchar(c);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct FormattingTraits<Encoding::Unicode>
|
||||
static uint characterCode(QChar c)
|
||||
{
|
||||
static ushort code(QChar c) { return c.unicode(); }
|
||||
};
|
||||
return c.unicode();
|
||||
}
|
||||
|
||||
template <Encoding e, class Iterator>
|
||||
static uint characterCode(uint c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
static void formatStringSequence(QTextStream &str, Iterator it, Iterator end,
|
||||
const QString &indent,
|
||||
int escapeIntegerBase, int escapeWidth,
|
||||
|
@ -262,13 +263,13 @@ static void formatStringSequence(QTextStream &str, Iterator it, Iterator end,
|
|||
str << '"';
|
||||
int length = 0;
|
||||
while (it != end) {
|
||||
const auto code = FormattingTraits<e>::code(*it);
|
||||
const auto code = characterCode(*it);
|
||||
if (code >= 0x80) {
|
||||
length += formatEscapedNumber(str, code, escapeIntegerBase, escapeWidth, escapePrefix);
|
||||
} else if (const int l = formatSpecialCharacter(str, code)) {
|
||||
length += l;
|
||||
} else if (code != '\r') {
|
||||
str << *it;
|
||||
str << char(code);
|
||||
++length;
|
||||
}
|
||||
++it;
|
||||
|
@ -280,6 +281,11 @@ static void formatStringSequence(QTextStream &str, Iterator it, Iterator end,
|
|||
str << '"';
|
||||
}
|
||||
|
||||
static bool isSurrogate(QChar c)
|
||||
{
|
||||
return c.isSurrogate();
|
||||
}
|
||||
|
||||
void _formatString(QTextStream &str, const QString &value, const QString &indent,
|
||||
bool qString)
|
||||
{
|
||||
|
@ -289,17 +295,20 @@ void _formatString(QTextStream &str, const QString &value, const QString &indent
|
|||
if (qString && _language == Language::Cpp)
|
||||
str << "QString::fromUtf8(";
|
||||
const QByteArray utf8 = value.toUtf8();
|
||||
formatStringSequence<Encoding::Utf8>(str, utf8.cbegin(), utf8.cend(), indent,
|
||||
8, 3);
|
||||
formatStringSequence(str, utf8.cbegin(), utf8.cend(), indent, 8, 3);
|
||||
if (qString && _language == Language::Cpp)
|
||||
str << ')';
|
||||
}
|
||||
break;
|
||||
// Special characters as 4 digit hex Unicode points (u8"\u00dcmlaut")
|
||||
case Encoding::Unicode:
|
||||
str << 'u'; // Python Unicode literal (would be UTF-16 in C++)
|
||||
formatStringSequence<Encoding::Unicode>(str, value.cbegin(), value.cend(), indent,
|
||||
16, 4, 'u');
|
||||
str << 'u'; // Python Unicode literal
|
||||
if (std::any_of(value.cbegin(), value.cend(), isSurrogate)) {
|
||||
const auto ucs4 = value.toUcs4();
|
||||
formatStringSequence(str, ucs4.cbegin(), ucs4.cend(), indent, 16, 8, 'U');
|
||||
} else {
|
||||
formatStringSequence(str, value.cbegin(), value.cend(), indent, 16, 4, 'u');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@
|
|||
<item>
|
||||
<widget class="QCheckBox" name="touchScreen">
|
||||
<property name="text">
|
||||
<string>Emulate touch screen (no mouse move)</string>
|
||||
<string>Emulate touch screen (no mouse move)🚀</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -704,7 +704,7 @@ public:
|
|||
TextLabel1_3->setText(QCoreApplication::translate("Config", "Skin", nullptr));
|
||||
skin->setItemText(0, QCoreApplication::translate("Config", "None", nullptr));
|
||||
|
||||
touchScreen->setText(QCoreApplication::translate("Config", "Emulate touch screen (no mouse move)", nullptr));
|
||||
touchScreen->setText(QCoreApplication::translate("Config", "Emulate touch screen (no mouse move)\360\237\232\200", nullptr));
|
||||
lcdScreen->setText(QCoreApplication::translate("Config", "Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", nullptr));
|
||||
TextLabel1->setText(QCoreApplication::translate("Config", "<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", nullptr));
|
||||
GroupBox1->setTitle(QCoreApplication::translate("Config", "Gamma", nullptr));
|
||||
|
|
|
@ -638,7 +638,7 @@ class Ui_Config(object):
|
|||
self.TextLabel1_3.setText(QCoreApplication.translate("Config", u"Skin", None))
|
||||
self.skin.setItemText(0, QCoreApplication.translate("Config", u"None", None))
|
||||
|
||||
self.touchScreen.setText(QCoreApplication.translate("Config", u"Emulate touch screen (no mouse move)", None))
|
||||
self.touchScreen.setText(QCoreApplication.translate("Config", u"Emulate touch screen (no mouse move)\U0001f680", None))
|
||||
self.lcdScreen.setText(QCoreApplication.translate("Config", u"Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", None))
|
||||
self.TextLabel1.setText(QCoreApplication.translate("Config", u"<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", None))
|
||||
self.GroupBox1.setTitle(QCoreApplication.translate("Config", u"Gamma", None))
|
||||
|
|
Loading…
Reference in New Issue