Merge remote-tracking branch 'origin/5.12' into dev

Change-Id: Ifb032dc19053481e1b0ede5c5c72540110d62567
This commit is contained in:
Qt Forward Merge Bot 2018-08-29 01:00:40 +02:00
commit e1c2183374
27 changed files with 255 additions and 51 deletions

View File

@ -1181,6 +1181,11 @@ void QCborArray::detach(qsizetype reserved)
Returns the offset of this iterator relative to \a other.
*/
uint qHash(const QCborArray &array, uint seed)
{
return qHashRange(array.begin(), array.end(), seed);
}
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, const QCborArray &a)
{

View File

@ -286,6 +286,8 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const
return concrete().toArray(a);
}
Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a);
#endif

View File

@ -1734,6 +1734,11 @@ void QCborMap::detach(qsizetype reserved)
\sa operator+=(), operator-()
*/
uint qHash(const QCborMap &map, uint seed)
{
return qHashRange(map.begin(), map.end(), seed);
}
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, const QCborMap &m)
{

View File

@ -337,6 +337,8 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
return concrete().toMap(m);
}
Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
#endif

View File

@ -2365,6 +2365,53 @@ inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept
{
}
uint qHash(const QCborValue &value, uint seed)
{
switch (value.type()) {
case QCborValue::Integer:
return qHash(value.toInteger(), seed);
case QCborValue::ByteArray:
return qHash(value.toByteArray(), seed);
case QCborValue::String:
return qHash(value.toString(), seed);
case QCborValue::Array:
return qHash(value.toArray(), seed);
case QCborValue::Map:
return qHash(value.toMap(), seed);
case QCborValue::Tag: {
QtPrivate::QHashCombine hash;
seed = hash(seed, value.tag());
seed = hash(seed, value.taggedValue());
return seed;
}
case QCborValue::SimpleType:
break;
case QCborValue::False:
return qHash(false, seed);
case QCborValue::True:
return qHash(true, seed);
case QCborValue::Null:
return qHash(nullptr, seed);
case QCborValue::Undefined:
return seed;
case QCborValue::Double:
return qHash(value.toDouble(), seed);
case QCborValue::DateTime:
return qHash(value.toDateTime(), seed);
case QCborValue::Url:
return qHash(value.toUrl(), seed);
case QCborValue::RegularExpression:
return qHash(value.toRegularExpression(), seed);
case QCborValue::Uuid:
return qHash(value.toUuid(), seed);
case QCborValue::Invalid:
return seed;
}
Q_ASSERT(value.isSimpleType());
return qHash(value.toSimpleType(), seed);
}
#if !defined(QT_NO_DEBUG_STREAM)
static QDebug debugContents(QDebug &dbg, const QCborValue &v)
{

View File

@ -451,6 +451,8 @@ private:
qsizetype i;
};
Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v);
#endif

View File

@ -1237,6 +1237,10 @@ void QJsonArray::compact()
a = static_cast<QJsonPrivate::Array *>(d->header->root());
}
uint qHash(const QJsonArray &array, uint seed)
{
return qHashRange(array.begin(), array.end(), seed);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonArray &a)

View File

@ -265,6 +265,8 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray)
Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif

View File

@ -1292,6 +1292,17 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
insert(e->key(), val);
}
uint qHash(const QJsonObject &object, uint seed)
{
QtPrivate::QHashCombine hash;
for (auto it = object.begin(), end = object.end(); it != end; ++it) {
const QString key = it.key();
const QJsonValue value = it.value();
seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
}
return seed;
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
{

View File

@ -262,6 +262,8 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject)
Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif

View File

@ -876,6 +876,28 @@ QJsonValue QJsonValueRef::toValue() const
return o->valueAt(index);
}
uint qHash(const QJsonValue &value, uint seed)
{
switch (value.type()) {
case QJsonValue::Null:
return qHash(nullptr, seed);
case QJsonValue::Bool:
return qHash(value.toBool(), seed);
case QJsonValue::Double:
return qHash(value.toDouble(), seed);
case QJsonValue::String:
return qHash(value.toString(), seed);
case QJsonValue::Array:
return qHash(value.toArray(), seed);
case QJsonValue::Object:
return qHash(value.toObject(), seed);
case QJsonValue::Undefined:
return seed;
}
Q_UNREACHABLE();
return 0;
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{

View File

@ -247,6 +247,8 @@ public:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif

View File

@ -104,6 +104,11 @@ Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed =
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW;
Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) Q_DECL_NOTHROW
{
return qHash(reinterpret_cast<quintptr>(nullptr), seed);
}
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
return qHash(reinterpret_cast<quintptr>(key), seed);

View File

@ -799,9 +799,9 @@ enum PlatformFieldValue {
PlatformId_Microsoft = 3
};
FontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes)
QFontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes)
{
FontNames out;
QFontNames out;
const int NameRecordSize = 12;
const int MS_LangIdEnglish = 0x009;
@ -947,7 +947,7 @@ QString qt_getEnglishName(const QString &familyName, bool includeStyle)
goto error;
{
const FontNames names = qt_getCanonicalFontNames(table, bytes);
const QFontNames names = qt_getCanonicalFontNames(table, bytes);
i18n_name = names.name;
if (includeStyle)
i18n_name += QLatin1Char(' ') + names.style;
@ -963,9 +963,9 @@ error:
}
// Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions.
FontNames qt_getCanonicalFontNames(const LOGFONT &lf)
QFontNames qt_getCanonicalFontNames(const LOGFONT &lf)
{
FontNames fontNames;
QFontNames fontNames;
HDC hdc = GetDC(0);
HFONT hfont = CreateFontIndirect(&lf);
@ -1054,7 +1054,7 @@ static bool addFontToDatabase(QString familyName,
QString subFamilyStyle;
if (ttf) {
// Look-up names registered in the font
FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
QFontNames canonicalNames = qt_getCanonicalFontNames(logFont);
if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
englishName = canonicalNames.name;
if (!canonicalNames.preferredName.isEmpty()) {
@ -1488,7 +1488,7 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag,
}
static void getFamiliesAndSignatures(const QByteArray &fontData,
QList<FontNames> *families,
QList<QFontNames> *families,
QVector<FONTSIGNATURE> *signatures)
{
const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
@ -1504,7 +1504,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
if (!table)
continue;
FontNames names = qt_getCanonicalFontNames(table, length);
QFontNames names = qt_getCanonicalFontNames(table, length);
if (names.name.isEmpty())
continue;
@ -1535,7 +1535,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
WinApplicationFont font;
font.fileName = fileName;
QVector<FONTSIGNATURE> signatures;
QList<FontNames> families;
QList<QFontNames> families;
QStringList familyNames;
if (!fontData.isEmpty()) {

View File

@ -210,7 +210,7 @@ static bool addFontToDatabase(QString familyName,
QString subFamilyStyle;
if (ttf) {
// Look-up names registered in the font
FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
QFontNames canonicalNames = qt_getCanonicalFontNames(logFont);
if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
englishName = canonicalNames.name;
if (!canonicalNames.preferredName.isEmpty()) {

View File

@ -168,7 +168,8 @@ inline quint16 qt_getUShort(const unsigned char *p)
return val;
}
struct FontNames {
struct QFontNames
{
QString name; // e.g. "DejaVu Sans Condensed"
QString style; // e.g. "Italic"
QString preferredName; // e.g. "DejaVu Sans"
@ -177,7 +178,7 @@ struct FontNames {
bool qt_localizedName(const QString &name);
QString qt_getEnglishName(const QString &familyName, bool includeStyle = false);
FontNames qt_getCanonicalFontNames(const LOGFONT &lf);
QFontNames qt_getCanonicalFontNames(const LOGFONT &lf);
QT_END_NAMESPACE

View File

@ -197,6 +197,7 @@ void QWindowsUser32DLL::init()
enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
getPointerType = (GetPointerType)library.resolve("GetPointerType");
getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
@ -212,7 +213,8 @@ void QWindowsUser32DLL::init()
bool QWindowsUser32DLL::supportsPointerApi()
{
return enableMouseInPointer && getPointerType && getPointerInfo && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo;
return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
&& getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo;
}
void QWindowsShcoreDLL::init()

View File

@ -89,6 +89,7 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
@ -105,6 +106,7 @@ struct QWindowsUser32DLL
EnableMouseInPointer enableMouseInPointer = nullptr;
GetPointerType getPointerType = nullptr;
GetPointerInfo getPointerInfo = nullptr;
GetPointerDeviceRects getPointerDeviceRects = nullptr;
GetPointerTouchInfo getPointerTouchInfo = nullptr;
GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
GetPointerPenInfo getPointerPenInfo = nullptr;

View File

@ -428,9 +428,18 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
return false; // Let DefWindowProc() handle Non Client messages.
POINTER_PEN_INFO *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
RECT pRect, dRect;
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
const quint32 pointerId = penInfo->pointerInfo.pointerId;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
/ (pRect.right - pRect.left) * (dRect.right - dRect.left),
dRect.top + qreal(penInfo->pointerInfo.ptHimetricLocation.y - pRect.top)
/ (pRect.bottom - pRect.top) * (dRect.bottom - dRect.top));
const qreal pressure = (penInfo->penMask & PEN_MASK_PRESSURE) ? qreal(penInfo->pressure) / 1024.0 : 0.5;
const qreal rotation = (penInfo->penMask & PEN_MASK_ROTATION) ? qreal(penInfo->rotation) : 0.0;
const qreal tangentialPressure = 0.0;
@ -438,6 +447,13 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
const int yTilt = (penInfo->penMask & PEN_MASK_TILT_Y) ? penInfo->tiltY : 0;
const int z = 0;
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
<< __FUNCTION__ << " pointerId=" << pointerId
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
<< " message=" << hex << msg.message
<< " flags=" << hex << penInfo->pointerInfo.pointerFlags;
const QTabletEvent::TabletDevice device = QTabletEvent::Stylus;
QTabletEvent::PointerType type;
Qt::MouseButtons mouseButtons;
@ -491,16 +507,18 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
QWindowSystemInterface::handleTabletEvent(target, localPos, globalPos, device, type, mouseButtons,
QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
pointerId, keyModifiers);
QEvent::Type eventType;
Qt::MouseButton button;
getMouseEventInfo(msg.message, penInfo->pointerInfo.ButtonChangeType, globalPos, &eventType, &button);
if (!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) {
QEvent::Type eventType;
Qt::MouseButton button;
getMouseEventInfo(msg.message, penInfo->pointerInfo.ButtonChangeType, globalPos, &eventType, &button);
QWindowSystemInterface::handleMouseEvent(target, localPos, globalPos, mouseButtons, button, eventType,
keyModifiers, Qt::MouseEventSynthesizedByQt);
QWindowSystemInterface::handleMouseEvent(target, localPos, globalPos, mouseButtons, button, eventType,
keyModifiers, Qt::MouseEventSynthesizedByQt);
}
break;
}
}

View File

@ -1779,39 +1779,26 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
_glyphs, positions);
if (_glyphs.size() == 0) {
if (_glyphs.isEmpty()) {
SelectObject(hdc, old_font);
return;
}
bool outputEntireItem = _glyphs.size() > 0;
if (outputEntireItem) {
options |= ETO_PDY;
QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
QVarLengthArray<wchar_t> g(_glyphs.size());
for (int i=0; i<_glyphs.size() - 1; ++i) {
glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
g[i] = _glyphs[i];
}
glyphDistances[(_glyphs.size() - 1) * 2] = 0;
glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
g.constData(), _glyphs.size(),
glyphDistances.data());
} else {
int i = 0;
while(i < _glyphs.size()) {
wchar_t g = _glyphs[i];
ExtTextOut(hdc, qRound(positions[i].x),
qRound(positions[i].y), options, 0,
&g, 1, 0);
++i;
}
options |= ETO_PDY;
QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
QVarLengthArray<wchar_t> g(_glyphs.size());
const int lastGlyph = _glyphs.size() - 1;
for (int i = 0; i < lastGlyph; ++i) {
glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
g[i] = _glyphs[i];
}
glyphDistances[lastGlyph * 2] = 0;
glyphDistances[lastGlyph * 2 + 1] = 0;
g[lastGlyph] = _glyphs[lastGlyph];
ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, nullptr,
g.constData(), _glyphs.size(),
glyphDistances.data());
}
win_xform.eM11 = win_xform.eM22 = 1.0;

View File

@ -942,10 +942,12 @@ void QSqlQuery::clear()
query. See the \l{QSqlQuery examples}{Detailed Description} for
examples.
Portability note: Some databases choose to delay preparing a query
Portability notes: Some databases choose to delay preparing a query
until it is executed the first time. In this case, preparing a
syntactically wrong query succeeds, but every consecutive exec()
will fail.
When the database does not support named placeholders directly,
the placeholder can only contain characters in the range [a-zA-Z0-9_].
For SQLite, the query string can contain only one statement at a time.
If more than one statement is given, the function returns \c false.

View File

@ -75,7 +75,7 @@ public:
void initColOffsets(int size);
int columnInQuery(int modelColumn) const;
mutable QSqlQuery query;
mutable QSqlQuery query = { QSqlQuery(0) };
mutable QSqlError error;
QModelIndex bottom;
QSqlRecord rec;

View File

@ -93,7 +93,7 @@ public:
QSqlTableModel::EditStrategy strategy;
bool busyInsertingRows;
QSqlQuery editQuery;
QSqlQuery editQuery = { QSqlQuery(0) };
QSqlIndex primaryIndex;
QString tableName;
QString filter;

View File

@ -3369,7 +3369,9 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position)
sectionIndicator->resize(w, h);
#endif
QPixmap pm(w, h);
const qreal pixmapDevicePixelRatio = q->devicePixelRatioF();
QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
pm.setDevicePixelRatio(pixmapDevicePixelRatio);
pm.fill(QColor(0, 0, 0, 45));
QRect rect(0, 0, w, h);

View File

@ -2744,6 +2744,37 @@ void tst_QLocale::formattedDataSize_data()
#undef ROWQ
#undef ROWB
}
// Languages which don't use a Latin alphabet
const QLocale::DataSizeFormats iecFormat = QLocale::DataSizeIecFormat;
const QLocale::DataSizeFormats traditionalFormat = QLocale::DataSizeTraditionalFormat;
const QLocale::DataSizeFormats siFormat = QLocale::DataSizeSIFormat;
const QLocale::Language lang = QLocale::Russian;
QTest::newRow("Russian-IEC-0") << lang << 2 << iecFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
QTest::newRow("Russian-IEC-10") << lang << 2 << iecFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
// CLDR doesn't provide IEC prefixes (yet?) so they aren't getting translated
QTest::newRow("Russian-IEC-12Ki") << lang << 2 << iecFormat << 12345 << QString("12,06 KiB");
QTest::newRow("Russian-IEC-16Ki") << lang << 2 << iecFormat << 16384 << QString("16,00 KiB");
QTest::newRow("Russian-IEC-1235k") << lang << 2 << iecFormat << 1234567 << QString("1,18 MiB");
QTest::newRow("Russian-IEC-1374k") << lang << 2 << iecFormat << 1374744 << QString("1,31 MiB");
QTest::newRow("Russian-IEC-1234M") << lang << 2 << iecFormat << 1234567890 << QString("1,15 GiB");
QTest::newRow("Russian-Trad-0") << lang << 2 << traditionalFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
QTest::newRow("Russian-Trad-10") << lang << 2 << traditionalFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
QTest::newRow("Russian-Trad-12Ki") << lang << 2 << traditionalFormat << 12345 << QString("12,06 \u043A\u0411");
QTest::newRow("Russian-Trad-16Ki") << lang << 2 << traditionalFormat << 16384 << QString("16,00 \u043A\u0411");
QTest::newRow("Russian-Trad-1235k") << lang << 2 << traditionalFormat << 1234567 << QString("1,18 \u041C\u0411");
QTest::newRow("Russian-Trad-1374k") << lang << 2 << traditionalFormat << 1374744 << QString("1,31 \u041C\u0411");
QTest::newRow("Russian-Trad-1234M") << lang << 2 << traditionalFormat << 1234567890 << QString("1,15 \u0413\u0411");
QTest::newRow("Russian-Decimal-0") << lang << 2 << siFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
QTest::newRow("Russian-Decimal-10") << lang << 2 << siFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
QTest::newRow("Russian-Decimal-16Ki") << lang << 2 << siFormat << 16384 << QString("16,38 \u043A\u0411");
QTest::newRow("Russian-Decimal-1234k") << lang << 2 << siFormat << 1234567 << QString("1,23 \u041C\u0411");
QTest::newRow("Russian-Decimal-1374k") << lang << 2 << siFormat << 1374744 << QString("1,37 \u041C\u0411");
QTest::newRow("Russian-Decimal-1234M") << lang << 2 << siFormat << 1234567890 << QString("1,23 \u0413\u0411");
}
void tst_QLocale::formattedDataSize()

View File

@ -1,5 +1,6 @@
[]
rhel-7.4
ubuntu-18.04
[customGesture]
# QTBUG-67254
ubuntu

View File

@ -31,11 +31,29 @@
#include "../../kernel/qsqldatabase/tst_databases.h"
#include <QtSql>
#include <QtSql/private/qsqltablemodel_p.h>
#include <QThread>
const QString test(qTableName("test", __FILE__, QSqlDatabase())),
test2(qTableName("test2", __FILE__, QSqlDatabase())),
test3(qTableName("test3", __FILE__, QSqlDatabase()));
// In order to catch when the warning message occurs, indicating that the database belongs to another
// thread, we have to install our own message handler. To ensure that the test reporting still happens
// as before, we call the originating one.
//
// For now, this is only called inside the modelInAnotherThread() test
QtMessageHandler oldHandler = nullptr;
void sqlTableModelMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
if (type == QtWarningMsg &&
msg == "QSqlDatabasePrivate::database: requested database does not "
"belong to the calling thread.") {
QFAIL("Requested database does not belong to the calling thread.");
}
if (oldHandler)
oldHandler(type, context, msg);
}
class tst_QSqlTableModel : public QObject
{
@ -116,6 +134,7 @@ private slots:
void sqlite_bigTable_data() { generic_data("QSQLITE"); }
void sqlite_bigTable();
void modelInAnotherThread();
// bug specific tests
void insertRecordBeforeSelect_data() { generic_data(); }
@ -276,6 +295,10 @@ void tst_QSqlTableModel::init()
void tst_QSqlTableModel::cleanup()
{
recreateTestTables();
if (oldHandler) {
qInstallMessageHandler(oldHandler);
oldHandler = nullptr;
}
}
void tst_QSqlTableModel::select()
@ -2100,5 +2123,29 @@ void tst_QSqlTableModel::invalidFilterAndHeaderData()
QVERIFY(!v.isValid());
}
class SqlThread : public QThread
{
public:
SqlThread() : QThread() {}
void run()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "non-default-connection");
QSqlTableModel stm(nullptr, db);
isDone = true;
}
bool isDone = false;
};
void tst_QSqlTableModel::modelInAnotherThread()
{
oldHandler = qInstallMessageHandler(sqlTableModelMessageHandler);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
CHECK_DATABASE(db);
SqlThread t;
t.start();
QTRY_VERIFY(t.isDone);
QVERIFY(t.isFinished());
}
QTEST_MAIN(tst_QSqlTableModel)
#include "tst_qsqltablemodel.moc"