Reverse iteration in QMetaEnum::valueToKeys().

Otherwise, values that are composed of others are not handled
correctly. For example,
Qt::Dialog|Qt::FramelessWindowHint (Qt::Dialog=0x2|Qt::Window)
is currently output as
"Window|FramelessWindowHint" since
Qt::Window matches first and its bits are removed from the flag value
so that Qt::Dialog in the next iteration no longer matches.

Change-Id: I67db5c977c75f887392aa8f345c5e6e9d82c5c26
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Friedemann Kleint 2015-02-17 09:23:29 +01:00 committed by David Faure
parent 081afb2a16
commit 05e0dfa006
2 changed files with 38 additions and 3 deletions

View File

@ -2665,13 +2665,14 @@ QByteArray QMetaEnum::valueToKeys(int value) const
int count = mobj->d.data[handle + 2]; int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3]; int data = mobj->d.data[handle + 3];
int v = value; int v = value;
for(int i = 0; i < count; i++) { // reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
for (int i = count - 1; i >= 0; --i) {
int k = mobj->d.data[data + 2*i + 1]; int k = mobj->d.data[data + 2*i + 1];
if ((k != 0 && (v & k) == k ) || (k == value)) { if ((k != 0 && (v & k) == k ) || (k == value)) {
v = v & ~k; v = v & ~k;
if (!keys.isEmpty()) if (!keys.isEmpty())
keys += '|'; keys.prepend('|');
keys += stringData(mobj, mobj->d.data[data + 2*i]); keys.prepend(stringData(mobj, mobj->d.data[data + 2*i]));
} }
} }
return keys; return keys;

View File

@ -46,6 +46,8 @@ public:
private slots: private slots:
void fromType(); void fromType();
void valuesToKeys_data();
void valuesToKeys();
}; };
void tst_QMetaEnum::fromType() void tst_QMetaEnum::fromType()
@ -57,5 +59,37 @@ void tst_QMetaEnum::fromType()
QCOMPARE(meta.keyCount(), 2); QCOMPARE(meta.keyCount(), 2);
} }
Q_DECLARE_METATYPE(Qt::WindowFlags)
void tst_QMetaEnum::valuesToKeys_data()
{
QTest::addColumn<Qt::WindowFlags>("windowFlags");
QTest::addColumn<QByteArray>("expected");
QTest::newRow("Window")
<< Qt::WindowFlags(Qt::Window)
<< QByteArrayLiteral("Window");
// Verify that Qt::Dialog does not cause 'Window' to appear in the output.
QTest::newRow("Frameless_Dialog")
<< (Qt::Dialog | Qt::FramelessWindowHint)
<< QByteArrayLiteral("Dialog|FramelessWindowHint");
// Similarly, Qt::WindowMinMaxButtonsHint should not show up as
// WindowMinimizeButtonHint|WindowMaximizeButtonHint
QTest::newRow("Tool_MinMax_StaysOnTop")
<< (Qt::Tool | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint)
<< QByteArrayLiteral("Tool|WindowMinMaxButtonsHint|WindowStaysOnTopHint");
}
void tst_QMetaEnum::valuesToKeys()
{
QFETCH(Qt::WindowFlags, windowFlags);
QFETCH(QByteArray, expected);
QMetaEnum me = QMetaEnum::fromType<Qt::WindowFlags>();
QCOMPARE(me.valueToKeys(windowFlags), expected);
}
QTEST_MAIN(tst_QMetaEnum) QTEST_MAIN(tst_QMetaEnum)
#include "tst_qmetaenum.moc" #include "tst_qmetaenum.moc"