summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-05-20 09:03:37 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-05-20 09:03:37 (GMT)
commit7a1accc89c5c45ef514ebf0e7693cd9522fa0362 (patch)
tree61dcb0da38b9e1c803183f5122ba015a700509ee
parent99f6250a4ac031b70757442715b226bc339ab699 (diff)
parent89a5f382e1eff75c3d3f015b3fce0a58b8079e04 (diff)
downloadQt-7a1accc89c5c45ef514ebf0e7693cd9522fa0362.zip
Qt-7a1accc89c5c45ef514ebf0e7693cd9522fa0362.tar.gz
Qt-7a1accc89c5c45ef514ebf0e7693cd9522fa0362.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2: improve Unicode Normalization autotest more subtests for QChar nano optimization of canonicalOrderHelper() fix canonicalOrderHelper() for some corner case use new QChar::requiresSurrogates() instead of hardcoded value prevent fake normalization prefer QChar::*surrogate() over hardcoded values Fixed an assert in QMenu
-rw-r--r--src/corelib/tools/qchar.cpp38
-rw-r--r--src/corelib/tools/qstring.cpp12
-rw-r--r--src/gui/widgets/qmenu.cpp12
-rw-r--r--tests/auto/qchar/tst_qchar.cpp104
-rw-r--r--tests/auto/qmenu/tst_qmenu.cpp54
5 files changed, 160 insertions, 60 deletions
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index ddb1516..ed0af4e 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -1480,9 +1480,9 @@ static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion
if (!d || (canonical && tag != QChar::Canonical))
continue;
- s.replace(uc - utf16, ucs4 > 0x10000 ? 2 : 1, (const QChar *)d, length);
- // since the insert invalidates the pointers and we do decomposition recursive
int pos = uc - utf16;
+ s.replace(pos, QChar::requiresSurrogates(ucs4) ? 2 : 1, reinterpret_cast<const QChar *>(d), length);
+ // since the insert invalidates the pointers and we do decomposition recursive
utf16 = reinterpret_cast<unsigned short *>(s.data());
uc = utf16 + pos + length;
}
@@ -1567,46 +1567,52 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in
int p2 = pos+1;
uint u1 = s.at(pos).unicode();
if (QChar(u1).isHighSurrogate()) {
- ushort low = s.at(pos+1).unicode();
+ ushort low = s.at(p2).unicode();
if (QChar(low).isLowSurrogate()) {
- p2++;
u1 = QChar::surrogateToUcs4(u1, low);
if (p2 >= l)
break;
+ ++p2;
}
}
uint u2 = s.at(p2).unicode();
- if (QChar(u2).isHighSurrogate() && p2 < l-1) {
+ if (QChar(u2).isHighSurrogate() && p2 < l) {
ushort low = s.at(p2+1).unicode();
if (QChar(low).isLowSurrogate()) {
- p2++;
u2 = QChar::surrogateToUcs4(u2, low);
+ ++p2;
}
}
- int c2 = QChar::combiningClass(u2);
- if (QChar::unicodeVersion(u2) > version)
- c2 = 0;
-
+ ushort c2 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u2);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c2 = p->combiningClass;
+ }
if (c2 == 0) {
pos = p2+1;
continue;
}
- int c1 = QChar::combiningClass(u1);
- if (QChar::unicodeVersion(u1) > version)
- c1 = 0;
+
+ ushort c1 = 0;
+ {
+ const QUnicodeTables::Properties *p = qGetProp(u1);
+ if ((QChar::UnicodeVersion)p->unicodeVersion <= version)
+ c1 = p->combiningClass;
+ }
if (c1 > c2) {
QChar *uc = s.data();
int p = pos;
// exchange characters
- if (u2 < 0x10000) {
+ if (!QChar::requiresSurrogates(u2)) {
uc[p++] = u2;
} else {
uc[p++] = QChar::highSurrogate(u2);
uc[p++] = QChar::lowSurrogate(u2);
}
- if (u1 < 0x10000) {
+ if (!QChar::requiresSurrogates(u1)) {
uc[p++] = u1;
} else {
uc[p++] = QChar::highSurrogate(u1);
@@ -1618,7 +1624,7 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in
--pos;
} else {
++pos;
- if (u1 > 0x10000)
+ if (QChar::requiresSurrogates(u1))
++pos;
}
}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 612c492..6acbcec 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -939,11 +939,11 @@ int QString::toWCharArray(wchar_t *array) const
const unsigned short *uc = utf16();
for (int i = 0; i < length(); ++i) {
uint u = uc[i];
- if (u >= 0xd800 && u < 0xdc00 && i < length()-1) {
+ if (QChar::isHighSurrogate(u) && i + 1 < length()) {
ushort low = uc[i+1];
- if (low >= 0xdc00 && low < 0xe000) {
+ if (QChar::isLowSurrogate(low)) {
+ u = QChar::surrogateToUcs4(u, low);
++i;
- u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
}
}
*a = wchar_t(u);
@@ -6195,8 +6195,10 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::
if (simple)
return;
- QString &s = *data;
- if (version != UNICODE_DATA_VERSION) {
+ if (version == QChar::Unicode_Unassigned) {
+ version = UNICODE_DATA_VERSION;
+ } else if (version != UNICODE_DATA_VERSION) {
+ QString &s = *data;
for (int i = 0; i < NumNormalizationCorrections; ++i) {
const NormalizationCorrection &n = uc_normalization_corrections[i];
if (n.version > version) {
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index f84059d..7941c4e 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -983,19 +983,9 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
return false;
}
-class ExceptionGuard
-{
-public:
- inline ExceptionGuard(bool *w = 0) : watched(w) { Q_ASSERT(!(*watched)); *watched = true; }
- inline ~ExceptionGuard() { *watched = false; }
- inline operator bool() { return *watched; }
-private:
- bool *watched;
-};
-
void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self)
{
- ExceptionGuard guard(&activationRecursionGuard);
+ QBoolBlocker guard(activationRecursionGuard);
#ifdef QT3_SUPPORT
const int actionId = q_func()->findIdForAction(action);
#endif
diff --git a/tests/auto/qchar/tst_qchar.cpp b/tests/auto/qchar/tst_qchar.cpp
index 5ca2255..93aaf96 100644
--- a/tests/auto/qchar/tst_qchar.cpp
+++ b/tests/auto/qchar/tst_qchar.cpp
@@ -43,6 +43,7 @@
#include <QtTest/QtTest>
#include <qchar.h>
#include <qfile.h>
+#include <qstringlist.h>
#include <private/qunicodetables_p.h>
#if defined(Q_OS_WINCE)
#include <qcoreapplication.h>
@@ -75,6 +76,7 @@ private slots:
void isPrint();
void isUpper();
void isLower();
+ void isTitle();
void category();
void direction();
void joining();
@@ -83,7 +85,9 @@ private slots:
void decomposition();
// void ligature();
void lineBreakClass();
+ void normalization_data();
void normalization();
+ void normalization_manual();
void normalizationCorrections();
void unicodeVersion();
#if defined(Q_OS_WINCE)
@@ -234,6 +238,11 @@ void tst_QChar::isUpper()
QVERIFY(!QChar('?').isUpper());
QVERIFY(QChar(0xC2).isUpper()); // A with ^
QVERIFY(!QChar(0xE2).isUpper()); // a with ^
+
+ for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
+ if (QChar::category(codepoint) == QChar::Letter_Uppercase)
+ QVERIFY(codepoint == QChar::toUpper(codepoint));
+ }
}
void tst_QChar::isLower()
@@ -245,6 +254,19 @@ void tst_QChar::isLower()
QVERIFY(!QChar('?').isLower());
QVERIFY(!QChar(0xC2).isLower()); // A with ^
QVERIFY(QChar(0xE2).isLower()); // a with ^
+
+ for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
+ if (QChar::category(codepoint) == QChar::Letter_Lowercase)
+ QVERIFY(codepoint == QChar::toLower(codepoint));
+ }
+}
+
+void tst_QChar::isTitle()
+{
+ for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
+ if (QChar::category(codepoint) == QChar::Letter_Titlecase)
+ QVERIFY(codepoint == QChar::toTitleCase(codepoint));
+ }
}
void tst_QChar::category()
@@ -486,31 +508,13 @@ void tst_QChar::lineBreakClass()
QVERIFY(QUnicodeTables::lineBreakClass(0x0fffdu) == QUnicodeTables::LineBreak_AL);
}
-void tst_QChar::normalization()
+void tst_QChar::normalization_data()
{
- {
- QString composed;
- composed += QChar(0xc0);
- QString decomposed;
- decomposed += QChar(0x41);
- decomposed += QChar(0x300);
+ QTest::addColumn<QStringList>("columns");
+ QTest::addColumn<int>("part");
- QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed);
- QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
- QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
- QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed);
- }
- {
- QString composed;
- composed += QChar(0xa0);
- QString decomposed;
- decomposed += QChar(0x20);
-
- QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed);
- QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
- QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
- QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed);
- }
+ int linenum = 0;
+ int part = 0;
QFile f(SRCDIR "NormalizationTest.txt");
QVERIFY(f.exists());
@@ -518,6 +522,8 @@ void tst_QChar::normalization()
f.open(QIODevice::ReadOnly);
while (!f.atEnd()) {
+ linenum++;
+
QByteArray line;
line.resize(1024);
int len = f.readLine(line.data(), 1024);
@@ -527,8 +533,11 @@ void tst_QChar::normalization()
if (comment >= 0)
line = line.left(comment);
- if (line.startsWith("@"))
+ if (line.startsWith("@")) {
+ if (line.startsWith("@Part") && line.size() > 5 && QChar(line.at(5)).isDigit())
+ part = QChar(line.at(5)).digitValue();
continue;
+ }
if (line.isEmpty())
continue;
@@ -541,8 +550,10 @@ void tst_QChar::normalization()
Q_ASSERT(l.size() == 5);
- QString columns[5];
+ QStringList columns;
for (int i = 0; i < 5; ++i) {
+ columns.append(QString());
+
QList<QByteArray> c = l.at(i).split(' ');
Q_ASSERT(!c.isEmpty());
@@ -553,15 +564,26 @@ void tst_QChar::normalization()
columns[i].append(QChar(uc));
else {
// convert to utf16
- uc -= 0x10000;
- ushort high = uc/0x400 + 0xd800;
- ushort low = uc%0x400 + 0xdc00;
+ ushort high = QChar::highSurrogate(uc);
+ ushort low = QChar::lowSurrogate(uc);
columns[i].append(QChar(high));
columns[i].append(QChar(low));
}
}
}
+ QString nm = QString("line #%1:").arg(linenum);
+ QTest::newRow(nm.toLatin1()) << columns << part;
+ }
+}
+
+void tst_QChar::normalization()
+{
+ QFETCH(QStringList, columns);
+ QFETCH(int, part);
+
+ Q_UNUSED(part)
+
// CONFORMANCE:
// 1. The following invariants must be true for all conformant implementations
//
@@ -611,6 +633,32 @@ void tst_QChar::normalization()
// #################
+}
+
+void tst_QChar::normalization_manual()
+{
+ {
+ QString composed;
+ composed += QChar(0xc0);
+ QString decomposed;
+ decomposed += QChar(0x41);
+ decomposed += QChar(0x300);
+
+ QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed);
+ }
+ {
+ QString composed;
+ composed += QChar(0xa0);
+ QString decomposed;
+ decomposed += QChar(0x20);
+
+ QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
+ QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed);
}
}
diff --git a/tests/auto/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp
index e10d7ee..c8dc516 100644
--- a/tests/auto/qmenu/tst_qmenu.cpp
+++ b/tests/auto/qmenu/tst_qmenu.cpp
@@ -51,6 +51,7 @@
#include <QListWidget>
#include <QWidgetAction>
#include <QDesktopWidget>
+#include <qdialog.h>
#include <qmenu.h>
#include <qstyle.h>
@@ -106,6 +107,7 @@ private slots:
void pushButtonPopulateOnAboutToShow();
void QTBUG7907_submenus_autoselect();
void QTBUG7411_submenus_activate();
+ void QTBUG_10735_crashWithDialog();
protected slots:
void onActivated(QAction*);
void onHighlighted(QAction*);
@@ -969,5 +971,57 @@ void tst_QMenu::QTBUG7411_submenus_activate()
+class MyMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ MyMenu() : m_currentIndex(0)
+ {
+ for (int i = 0; i < 2; ++i)
+ dialogActions[i] = addAction( QString("dialog %1").arg(i), dialogs + i, SLOT(exec()));
+ }
+
+
+ void activateAction(int index)
+ {
+ m_currentIndex = index;
+ popup(QPoint());
+ QTest::qWaitForWindowShown(this);
+ setActiveAction(dialogActions[index]);
+ QTimer::singleShot(0, this, SLOT(checkVisibility()));
+ QTest::keyClick(this, Qt::Key_Enter); //activation
+ }
+
+public slots:
+ void activateLastAction()
+ {
+ activateAction(1);
+ }
+
+ void checkVisibility()
+ {
+ QTRY_VERIFY(dialogs[m_currentIndex].isVisible());
+ if (m_currentIndex == 1) {
+ QApplication::closeAllWindows(); //this is the end of the test
+ }
+ }
+
+
+private:
+ QAction *dialogActions[2];
+ QDialog dialogs[2];
+ int m_currentIndex;
+};
+
+void tst_QMenu::QTBUG_10735_crashWithDialog()
+{
+ MyMenu menu;
+
+ QTimer::singleShot(1000, &menu, SLOT(activateLastAction()));
+ menu.activateAction(0);
+
+}
+
+
QTEST_MAIN(tst_QMenu)
#include "tst_qmenu.moc"