Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I69238f23882deebeaad46e4fdcf899ab22cc2b8f
This commit is contained in:
commit
11d7788c18
@ -1481,6 +1481,10 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
|
||||
"type": "error",
|
||||
"condition": "!features.stl",
|
||||
"message": "Qt requires a compliant STL library."
|
||||
},
|
||||
{
|
||||
"type": "emccVersion",
|
||||
"condition": "config.wasm"
|
||||
}
|
||||
],
|
||||
|
||||
|
@ -1226,6 +1226,12 @@ defineReplace(qtConfOutputPostProcess_publicPro) {
|
||||
"QT_RELEASE_DATE = $$config.input.qt_release_date"
|
||||
}
|
||||
|
||||
wasm: {
|
||||
qt_emcc_version = $$qtSystemEmccVersion()
|
||||
output += \
|
||||
"QT_EMCC_VERSION = $$qt_emcc_version"
|
||||
}
|
||||
|
||||
return($$output)
|
||||
}
|
||||
|
||||
@ -1258,6 +1264,12 @@ defineReplace(qtConfOutputPostProcess_publicHeader) {
|
||||
!isEmpty(config.input.qt_libinfix): \
|
||||
output += "$${LITERAL_HASH}define QT_LIBINFIX \"$$eval(config.input.qt_libinfix)\""
|
||||
|
||||
wasm: {
|
||||
qt_emcc_version = $$qtSystemEmccVersion()
|
||||
output += \
|
||||
"$${LITERAL_HASH}define QT_EMCC_VERSION \"$$qt_emcc_version\""
|
||||
}
|
||||
|
||||
return($$output)
|
||||
}
|
||||
|
||||
@ -1340,6 +1352,14 @@ defineTest(qtConfReport_buildMode) {
|
||||
qtConfReportPadded($$1, $$build_mode)
|
||||
}
|
||||
|
||||
defineTest(qtConfReport_emccVersion) {
|
||||
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||
!equals(EMCC_VERSION, $$REQ_VERSION) {
|
||||
qtConfAddReport("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $$EMCC_VERSION $$QT_EMCC_VERSION")
|
||||
}
|
||||
}
|
||||
|
||||
# ensure pristine environment for configuration
|
||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
|
||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)
|
||||
|
@ -6,16 +6,6 @@ isEmpty(QMAKE_MOD_RCC):QMAKE_MOD_RCC = qrc
|
||||
!contains(QMAKE_RESOURCE_FLAGS, -root):!isEmpty(QMAKE_RESOURCE_ROOT):QMAKE_RESOURCE_FLAGS += -root $$QMAKE_RESOURCE_ROOT
|
||||
!contains(QMAKE_RESOURCE_FLAGS, -name): QMAKE_RESOURCE_FLAGS += -name ${QMAKE_FILE_BASE}
|
||||
|
||||
# http://www.w3.org/TR/xml/#syntax
|
||||
defineReplace(xml_escape) {
|
||||
1 ~= s,&,&,
|
||||
1 ~= s,\',',
|
||||
1 ~= s,\",",
|
||||
1 ~= s,<,<,
|
||||
1 ~= s,>,>,
|
||||
return($$1)
|
||||
}
|
||||
|
||||
load(resources_functions)
|
||||
qtFlattenResources()
|
||||
|
||||
|
@ -1,5 +1,21 @@
|
||||
# http://www.w3.org/TR/xml/#syntax
|
||||
defineReplace(xml_escape) {
|
||||
1 ~= s,&,&,
|
||||
1 ~= s,\',',
|
||||
1 ~= s,\",",
|
||||
1 ~= s,<,<,
|
||||
1 ~= s,>,>,
|
||||
return($$1)
|
||||
}
|
||||
|
||||
defineTest(qtFlattenResources) {
|
||||
RESOURCES += qmake_immediate
|
||||
immediate = qmake_immediate$$QMAKE_RESOURCES_IMMEDIATE_NR
|
||||
defined(QMAKE_RESOURCES_IMMEDIATE_NR, var): \
|
||||
QMAKE_RESOURCES_IMMEDIATE_NR = $$num_add($$QMAKE_RESOURCES_IMMEDIATE_NR, 1)
|
||||
else: \
|
||||
QMAKE_RESOURCES_IMMEDIATE_NR = 1
|
||||
|
||||
RESOURCES += $$immediate
|
||||
for(resource, RESOURCES) {
|
||||
# Regular case of user qrc file
|
||||
contains(resource, ".*\\.qrc$"): \
|
||||
@ -7,10 +23,10 @@ defineTest(qtFlattenResources) {
|
||||
|
||||
# Fallback for stand-alone files/directories
|
||||
!defined($${resource}.files, var) {
|
||||
!equals(resource, qmake_immediate) {
|
||||
!equals(resource, $$immediate) {
|
||||
!exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
|
||||
warning("Failure to find: $$resource")
|
||||
qmake_immediate.files += $$resource
|
||||
$${immediate}.files += $$resource
|
||||
OTHER_FILES *= $$resource
|
||||
}
|
||||
RESOURCES -= $$resource
|
||||
@ -56,8 +72,9 @@ defineTest(qtFlattenResources) {
|
||||
RESOURCES -= $$resource
|
||||
RESOURCES += $$resource_file
|
||||
}
|
||||
export(QMAKE_RESOURCES_IMMEDIATE_NR)
|
||||
export(RESOURCES)
|
||||
export(OTHER_FILES)
|
||||
export(qmake_immediate.files)
|
||||
export($${immediate}.files)
|
||||
return(true)
|
||||
}
|
||||
|
25
mkspecs/features/wasm/default_pre.prf
Normal file
25
mkspecs/features/wasm/default_pre.prf
Normal file
@ -0,0 +1,25 @@
|
||||
load(default_pre)
|
||||
|
||||
defineReplace(qtEmccRecommendedVersion) {
|
||||
return (1.38.27)
|
||||
}
|
||||
|
||||
defineReplace(qtSystemEmccVersion) {
|
||||
E_VERSION = $$system("emcc -v 2>&1 | perl -alne $$shell_quote($_ = $F[9]; s/://; print;) ")
|
||||
return ($${E_VERSION})
|
||||
}
|
||||
|
||||
defineTest(qtConfTest_emccVersion) {
|
||||
|
||||
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||
|
||||
!defined(QT_EMCC_VERSION, var):!equals(EMCC_VERSION, $${REQ_VERSION}) {
|
||||
warning ("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $${EMCC_VERSION} ")
|
||||
}
|
||||
contains(TEMPLATE, .*app) {
|
||||
!equals(QT_EMCC_VERSION, $$EMCC_VERSION) {
|
||||
warning("This Qt was built with Emscripten version $${QT_EMCC_VERSION}. You have $${EMCC_VERSION}. The difference may cause issues.")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
|
||||
|
||||
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
|
||||
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
|
||||
|
||||
exists($$QMAKE_QT_CONFIG) {
|
||||
## this may be subject to change
|
||||
|
||||
qtConfig(thread) {
|
||||
|
||||
EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1
|
||||
@ -109,6 +112,8 @@ contains(TEMPLATE, .*app) {
|
||||
}
|
||||
}
|
||||
|
||||
qtConfTest_emccVersion()
|
||||
|
||||
# Pass --source-map-base on the linker line. This informs the
|
||||
# browser where to find the source files when debugging.
|
||||
WASM_SOURCE_MAP_BASE = http://localhost:8000/
|
||||
|
26
src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
vendored
Normal file
26
src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
From 676425e522e08eb0e7dfaacdac79a5de27542322 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Shaw <andy.shaw@qt.io>
|
||||
Date: Wed, 11 Dec 2019 10:51:22 +0100
|
||||
Subject: [PATCH 53/53] Fix CVE-2019-19244 in SQLite
|
||||
|
||||
Fixes: QTBUG-80635
|
||||
Change-Id: I718349e28ec76ea164dd50f2a985f2074dd6bdbd
|
||||
---
|
||||
src/3rdparty/sqlite/sqlite3.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
|
||||
index 8fd740b300..bd647ca1c2 100644
|
||||
--- a/src/3rdparty/sqlite/sqlite3.c
|
||||
+++ b/src/3rdparty/sqlite/sqlite3.c
|
||||
@@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
+ && p->pWin==0
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
--
|
||||
2.21.0 (Apple Git-122.2)
|
||||
|
1
src/3rdparty/sqlite/sqlite3.c
vendored
1
src/3rdparty/sqlite/sqlite3.c
vendored
@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
&& p->pWin==0
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
|
@ -84,10 +84,10 @@ QT_BEGIN_NAMESPACE
|
||||
must start and stop the timer in its thread; it is not possible to
|
||||
start a timer from another thread.
|
||||
|
||||
As a special case, a QTimer with a timeout of 0 will time out as
|
||||
soon as all the events in the window system's event queue have
|
||||
been processed. This can be used to do heavy work while providing
|
||||
a snappy user interface:
|
||||
As a special case, a QTimer with a timeout of 0 will time out as soon as
|
||||
possible, though the ordering between zero timers and other sources of
|
||||
events is unspecified. Zero timers can be used to do some work while still
|
||||
providing a snappy user interface:
|
||||
|
||||
\snippet timers/timers.cpp 4
|
||||
\snippet timers/timers.cpp 5
|
||||
|
@ -4534,15 +4534,24 @@ QSequentialIterable::const_iterator QSequentialIterable::end() const
|
||||
return it;
|
||||
}
|
||||
|
||||
static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
|
||||
QVariant v;
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
v = *reinterpret_cast<const QVariant*>(d.data);
|
||||
else
|
||||
v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
|
||||
if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
|
||||
QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data));
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the element at position \a idx in the container.
|
||||
*/
|
||||
QVariant QSequentialIterable::at(int idx) const
|
||||
{
|
||||
const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
return *reinterpret_cast<const QVariant*>(d.data);
|
||||
return QVariant(d.metaTypeId, d.data, d.flags);
|
||||
return variantFromVariantDataHelper(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4619,9 +4628,7 @@ QSequentialIterable::const_iterator::operator=(const const_iterator &other)
|
||||
const QVariant QSequentialIterable::const_iterator::operator*() const
|
||||
{
|
||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
return *reinterpret_cast<const QVariant*>(d.data);
|
||||
return QVariant(d.metaTypeId, d.data, d.flags);
|
||||
return variantFromVariantDataHelper(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4953,10 +4960,7 @@ QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
|
||||
const QVariant QAssociativeIterable::const_iterator::operator*() const
|
||||
{
|
||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
|
||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
return *reinterpret_cast<const QVariant*>(d.data);
|
||||
return v;
|
||||
return variantFromVariantDataHelper(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4965,10 +4969,7 @@ const QVariant QAssociativeIterable::const_iterator::operator*() const
|
||||
const QVariant QAssociativeIterable::const_iterator::key() const
|
||||
{
|
||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
|
||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
return *reinterpret_cast<const QVariant*>(d.data);
|
||||
return v;
|
||||
return variantFromVariantDataHelper(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4976,11 +4977,7 @@ const QVariant QAssociativeIterable::const_iterator::key() const
|
||||
*/
|
||||
const QVariant QAssociativeIterable::const_iterator::value() const
|
||||
{
|
||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
|
||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||
return *reinterpret_cast<const QVariant*>(d.data);
|
||||
return v;
|
||||
return operator*();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -105,6 +105,11 @@ inline T *v_cast(QVariant::Private *d, T * = nullptr)
|
||||
|
||||
#endif
|
||||
|
||||
enum QVariantConstructionFlags : uint {
|
||||
Default = 0x0,
|
||||
PointerType = 0x1,
|
||||
ShouldDeleteVariantData = 0x2 // only used in Q*Iterable
|
||||
};
|
||||
|
||||
//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
|
||||
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
|
||||
|
@ -1626,6 +1626,29 @@ qint64 QDate::daysTo(const QDate &d) const
|
||||
*/
|
||||
|
||||
#if QT_CONFIG(datestring)
|
||||
namespace {
|
||||
|
||||
struct ParsedInt { int value = 0; bool ok = false; };
|
||||
|
||||
/*
|
||||
/internal
|
||||
|
||||
Read an int that must be the whole text. QStringRef::toInt() will ignore
|
||||
spaces happily; but ISO date format should not.
|
||||
*/
|
||||
ParsedInt readInt(QStringView text)
|
||||
{
|
||||
ParsedInt result;
|
||||
for (const auto &ch : text) {
|
||||
if (ch.isSpace())
|
||||
return result;
|
||||
}
|
||||
result.value = QLocale::c().toInt(text, &result.ok);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the QDate represented by the \a string, using the
|
||||
\a format given, or an invalid date if the string cannot be
|
||||
@ -1677,17 +1700,18 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
|
||||
return QDate(year, month, day);
|
||||
}
|
||||
#endif // textdate
|
||||
case Qt::ISODate: {
|
||||
// Semi-strict parsing, must be long enough and have non-numeric separators
|
||||
if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
|
||||
|| (string.size() > 10 && string.at(10).isDigit())) {
|
||||
return QDate();
|
||||
}
|
||||
const int year = string.midRef(0, 4).toInt();
|
||||
if (year <= 0 || year > 9999)
|
||||
return QDate();
|
||||
return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
|
||||
case Qt::ISODate:
|
||||
// Semi-strict parsing, must be long enough and have punctuators as separators
|
||||
if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
|
||||
&& (string.size() == 10 || !string.at(10).isDigit())) {
|
||||
QStringView view(string);
|
||||
const ParsedInt year = readInt(view.mid(0, 4));
|
||||
const ParsedInt month = readInt(view.mid(5, 2));
|
||||
const ParsedInt day = readInt(view.mid(8, 2));
|
||||
if (year.ok && year.value > 0 && year.value <= 9999 && month.ok && day.ok)
|
||||
return QDate(year.value, month.value, day.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return QDate();
|
||||
}
|
||||
@ -2331,17 +2355,15 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
|
||||
*isMidnight24 = false;
|
||||
|
||||
const int size = string.size();
|
||||
if (size < 5)
|
||||
if (size < 5 || string.at(2) != QLatin1Char(':'))
|
||||
return QTime();
|
||||
|
||||
const QLocale C(QLocale::c());
|
||||
bool ok = false;
|
||||
int hour = C.toInt(string.mid(0, 2), &ok);
|
||||
if (!ok)
|
||||
return QTime();
|
||||
const int minute = C.toInt(string.mid(3, 2), &ok);
|
||||
if (!ok)
|
||||
ParsedInt hour = readInt(string.mid(0, 2));
|
||||
ParsedInt minute = readInt(string.mid(3, 2));
|
||||
if (!hour.ok || !minute.ok)
|
||||
return QTime();
|
||||
// FIXME: ISO 8601 allows [,.]\d+ after hour, just as it does after minute
|
||||
|
||||
int second = 0;
|
||||
int msec = 0;
|
||||
|
||||
@ -2361,44 +2383,56 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
|
||||
// will then be rounded up AND clamped to 999.
|
||||
|
||||
const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
|
||||
const long minuteFractionInt = C.toLong(minuteFractionStr, &ok);
|
||||
if (!ok)
|
||||
const ParsedInt parsed = readInt(minuteFractionStr);
|
||||
if (!parsed.ok)
|
||||
return QTime();
|
||||
const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.size()));
|
||||
const float secondWithMs
|
||||
= double(parsed.value) * 60 / (std::pow(double(10), minuteFractionStr.size()));
|
||||
|
||||
const float secondWithMs = minuteFraction * 60;
|
||||
const float secondNoMs = std::floor(secondWithMs);
|
||||
const float secondFraction = secondWithMs - secondNoMs;
|
||||
second = secondNoMs;
|
||||
second = std::floor(secondWithMs);
|
||||
const float secondFraction = secondWithMs - second;
|
||||
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
||||
} else {
|
||||
} else if (string.at(5) == QLatin1Char(':')) {
|
||||
// HH:mm:ss or HH:mm:ss.zzz
|
||||
second = C.toInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)), &ok);
|
||||
if (!ok)
|
||||
const ParsedInt parsed = readInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)));
|
||||
if (!parsed.ok)
|
||||
return QTime();
|
||||
if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
|
||||
second = parsed.value;
|
||||
if (size <= 8) {
|
||||
// No fractional part to read
|
||||
} else if (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.')) {
|
||||
QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
|
||||
// toInt() ignores leading spaces, so catch them before calling it
|
||||
bool ok = true;
|
||||
// Can't use readInt() here, as we *do* allow trailing space - but not leading:
|
||||
if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
|
||||
return QTime();
|
||||
// We do, however, want to ignore *trailing* spaces.
|
||||
msecStr = msecStr.trimmed();
|
||||
int msecInt = msecStr.isEmpty() ? 0 : C.toInt(msecStr, &ok);
|
||||
int msecInt = msecStr.isEmpty() ? 0 : QLocale::c().toInt(msecStr, &ok);
|
||||
if (!ok)
|
||||
return QTime();
|
||||
const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
|
||||
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
||||
} else {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // behavior change
|
||||
// Stray cruft after date-time: tolerate trailing space, but nothing else.
|
||||
for (const auto &ch : string.mid(8)) {
|
||||
if (!ch.isSpace())
|
||||
return QTime();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
return QTime();
|
||||
}
|
||||
|
||||
const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
|
||||
if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
|
||||
if (isISODate && hour.value == 24 && minute.value == 0 && second == 0 && msec == 0) {
|
||||
if (isMidnight24)
|
||||
*isMidnight24 = true;
|
||||
hour = 0;
|
||||
hour.value = 0;
|
||||
}
|
||||
|
||||
return QTime(hour, minute, second, msec);
|
||||
return QTime(hour.value, minute.value, second, msec);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1,5 +1,5 @@
|
||||
Please note that the DB2, Oracle and TDS client drivers are not distributed
|
||||
with the Qt Open Source Editions.
|
||||
Please note that the DB2, MySQL, Oracle and TDS client drivers are not
|
||||
distributed with the Qt Open Source Editions.
|
||||
|
||||
This is because the client libraries are distributed under a license which
|
||||
is not compatible with the GPL license.
|
||||
|
@ -692,40 +692,24 @@ QVariant QPSQLResult::data(int i)
|
||||
return dbl;
|
||||
}
|
||||
case QVariant::Date:
|
||||
if (val[0] == '\0') {
|
||||
return QVariant(QDate());
|
||||
} else {
|
||||
#if QT_CONFIG(datestring)
|
||||
return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));
|
||||
return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));
|
||||
#else
|
||||
return QVariant(QString::fromLatin1(val));
|
||||
return QVariant(QString::fromLatin1(val));
|
||||
#endif
|
||||
}
|
||||
case QVariant::Time: {
|
||||
const QString str = QString::fromLatin1(val);
|
||||
case QVariant::Time:
|
||||
#if QT_CONFIG(datestring)
|
||||
if (str.isEmpty())
|
||||
return QVariant(QTime());
|
||||
else
|
||||
return QVariant(QTime::fromString(str, Qt::ISODate));
|
||||
return QVariant(QTime::fromString(QString::fromLatin1(val), Qt::ISODate));
|
||||
#else
|
||||
return QVariant(str);
|
||||
return QVariant(QString::fromLatin1(val));
|
||||
#endif
|
||||
}
|
||||
case QVariant::DateTime: {
|
||||
QString dtval = QString::fromLatin1(val);
|
||||
case QVariant::DateTime:
|
||||
#if QT_CONFIG(datestring)
|
||||
if (dtval.length() < 10) {
|
||||
return QVariant(QDateTime());
|
||||
} else {
|
||||
QChar sign = dtval[dtval.size() - 3];
|
||||
if (sign == QLatin1Char('-') || sign == QLatin1Char('+')) dtval += QLatin1String(":00");
|
||||
return QVariant(QDateTime::fromString(dtval, Qt::ISODate).toLocalTime());
|
||||
}
|
||||
return QVariant(QDateTime::fromString(QString::fromLatin1(val),
|
||||
Qt::ISODate).toLocalTime());
|
||||
#else
|
||||
return QVariant(dtval);
|
||||
return QVariant(QString::fromLatin1(val));
|
||||
#endif
|
||||
}
|
||||
case QVariant::ByteArray: {
|
||||
size_t len;
|
||||
unsigned char *data = PQunescapeBytea((const unsigned char*)val, &len);
|
||||
|
@ -70,7 +70,6 @@ BEGIN
|
||||
END
|
||||
//! [1]
|
||||
|
||||
|
||||
//! [3]
|
||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||
qmake -- MYSQL_PREFIX=/usr/local
|
||||
@ -86,14 +85,15 @@ make install
|
||||
|
||||
//! [5]
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- MYSQL_INCDIR=C:/MySQL/include "MYSQL_LIBDIR=C:/MYSQL/MySQL Server <version>/lib/opt"
|
||||
qmake -- MYSQL_INCDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/include" MYSQL_LIBDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/lib"
|
||||
nmake sub-mysql
|
||||
nmake install
|
||||
//! [5]
|
||||
|
||||
|
||||
//! [6]
|
||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||
qmake -- "OCI_INCDIR=$ORACLE_HOME/rdbms/public" OCI_LIBDIR=$ORACLE_HOME/lib "OCI_LIBS=-lclntsh -lwtc9"
|
||||
qmake -- OCI_INCDIR="$ORACLE_HOME/rdbms/public" OCI_LIBDIR="$ORACLE_HOME/lib" OCI_LIBS="-lclntsh -lwtc9"
|
||||
make sub-oci
|
||||
//! [6]
|
||||
|
||||
@ -142,6 +142,7 @@ make sub-psql
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- PSQL_INCDIR=C:/psql/include PSQL_LIBDIR=C:/psql/lib/ms
|
||||
nmake sub-psql
|
||||
nmake install
|
||||
//! [15]
|
||||
|
||||
|
||||
@ -156,6 +157,7 @@ make sub-tds
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake
|
||||
nmake sub-tds
|
||||
nmake install
|
||||
//! [17]
|
||||
|
||||
|
||||
@ -168,8 +170,9 @@ make sub-db2
|
||||
|
||||
//! [20]
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- "DB2_PREFIX=<DB2 home>/sqllib"
|
||||
qmake -- DB2_PREFIX="<DB2 home>/sqllib"
|
||||
nmake sub-db2
|
||||
nmake install
|
||||
//! [20]
|
||||
|
||||
|
||||
@ -184,6 +187,7 @@ make sub-sqlite
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- -system-sqlite SQLITE3_PREFIX=C:/SQLITE
|
||||
nmake sub-sqlite
|
||||
nmake install
|
||||
//! [23]
|
||||
|
||||
|
||||
@ -205,6 +209,7 @@ make sub-ibase
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- IBASE_INCDIR=C:/interbase/include
|
||||
nmake sub-ibase
|
||||
nmake install
|
||||
//! [29]
|
||||
|
||||
|
||||
@ -212,17 +217,18 @@ nmake sub-ibase
|
||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||
qmake -- IBASE_INCDIR=C:/interbase/include IBASE_LIBS=-lfbclient
|
||||
nmake sub-ibase
|
||||
nmake install
|
||||
//! [30]
|
||||
|
||||
|
||||
//! [32]
|
||||
configure OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-lclntsh -lnnz10"
|
||||
configure OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib OCI_LIBS="-lclntsh -lnnz10"
|
||||
make
|
||||
//! [32]
|
||||
|
||||
//! [33]
|
||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||
qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10"
|
||||
qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib OCI_LIBS="-Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10"
|
||||
make sub-oci
|
||||
//! [33]
|
||||
|
||||
@ -250,3 +256,42 @@ q.exec(QString("CREATE TABLE %1 (id INTEGER)").arg(tableString));
|
||||
// Call toLower() on the string so that it can be matched
|
||||
QSqlRecord rec = database.record(tableString.toLower());
|
||||
//! [40]
|
||||
|
||||
//! [41]
|
||||
C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers>qmake -version
|
||||
QMake version 3.1
|
||||
Using Qt version 5.13.2 in C:/Qt5/5.13.2/mingw73_64/lib
|
||||
C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers>qmake -- MYSQL_INCDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/include" MYSQL_LIBDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/lib"
|
||||
Info: creating stash file C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers\.qmake.stash
|
||||
|
||||
Running configuration tests...
|
||||
Checking for DB2 (IBM)... no
|
||||
Checking for InterBase... no
|
||||
Checking for MySQL... yes
|
||||
Checking for OCI (Oracle)... no
|
||||
Checking for ODBC... yes
|
||||
Checking for PostgreSQL... no
|
||||
Checking for SQLite (version 2)... no
|
||||
Checking for TDS (Sybase)... no
|
||||
Done running configuration tests.
|
||||
|
||||
Configure summary:
|
||||
|
||||
Qt Sql Drivers:
|
||||
DB2 (IBM) .............................. no
|
||||
InterBase .............................. no
|
||||
MySql .................................. yes
|
||||
OCI (Oracle) ........................... no
|
||||
ODBC ................................... yes
|
||||
PostgreSQL ............................. no
|
||||
SQLite2 ................................ no
|
||||
SQLite ................................. yes
|
||||
Using system provided SQLite ......... no
|
||||
TDS (Sybase) ........................... no
|
||||
|
||||
Qt is now configured for building. Just run 'mingw32-make'.
|
||||
Once everything is built, you must run 'mingw32-make install'.
|
||||
Qt will be installed into 'C:\Qt5\5.13.2\mingw73_64'.
|
||||
|
||||
Prior to reconfiguration, make sure you remove any leftovers from the previous build.
|
||||
//! [41]
|
||||
|
@ -48,7 +48,7 @@
|
||||
\header \li Driver name \li DBMS
|
||||
\row \li \l{#QDB2}{QDB2} \li IBM DB2 (version 7.1 and above)
|
||||
\row \li \l{#QIBASE}{QIBASE} \li Borland InterBase
|
||||
\row \li \l{#QMYSQL}{QMYSQL} \li MySQL
|
||||
\row \li \l{#QMYSQL}{QMYSQL} \li MySQL (version 5.0 and above)
|
||||
\row \li \l{#QOCI}{QOCI} \li Oracle Call Interface Driver
|
||||
\row \li \l{#QODBC}{QODBC}
|
||||
\li Open Database Connectivity (ODBC) - Microsoft SQL Server and other
|
||||
@ -70,7 +70,8 @@
|
||||
access to the API exposed by the DBMS, and is typically shipped with it.
|
||||
Most installation programs also allow you to install "development
|
||||
libraries", and these are what you need. These libraries are responsible
|
||||
for the low-level communication with the DBMS.
|
||||
for the low-level communication with the DBMS. Also make sure to install
|
||||
the correct database libraries for your Qt architecture (32 or 64 bit).
|
||||
|
||||
\note When using Qt under Open Source terms but with a proprietary
|
||||
database, verify the client library's license compatibility with
|
||||
@ -91,11 +92,21 @@
|
||||
may be necessary to specify these paths using the \c *_INCDIR=,
|
||||
\c *_LIBDIR=, or \c *_PREFIX= command-line options. For example,
|
||||
if your MySQL files are installed in \c /usr/local/mysql (or in
|
||||
\c{C:\mysql} on Windows), then pass the following parameter to
|
||||
configure: \c MYSQL_PREFIX=/usr/local/mysql
|
||||
(or \c{MYSQL_PREFIX=C:\mysql} for Windows).
|
||||
\c{C:/Program Files/MySQL/MySQL Connector C 6.1} on Windows), then pass the
|
||||
following parameter to configure: \c MYSQL_PREFIX=/usr/local/mysql
|
||||
(or \c{MYSQL_PREFIX="C:/Program Files/MySQL/MySQL Connector C 6.1"} for Windows).
|
||||
The particulars for each driver are explained below.
|
||||
|
||||
If something goes wrong and you want qmake to recheck your
|
||||
available drivers, you must remove \e{config.cache} in
|
||||
\e{<QTDIR>/qtbase/src/plugins/sqldrivers} - otherwise qmake will not
|
||||
search for the available drivers again. If you encounter an error during
|
||||
the qmake stage, open \e{config.log} to see what went wrong.
|
||||
|
||||
A typical qmake run (in this case to configure for MySQL) looks like this:
|
||||
|
||||
\snippet code/doc_src_sql-driver.qdoc 41
|
||||
|
||||
Due to the practicalities of dealing with external dependencies,
|
||||
only the SQLite3 plugin is shipped with binary builds of Qt.
|
||||
To be able to add additional drivers to the Qt installation
|
||||
@ -112,11 +123,11 @@
|
||||
\section1 Driver Specifics
|
||||
|
||||
\target QMYSQL
|
||||
\section2 QMYSQL for MySQL 4 and higher
|
||||
\section2 QMYSQL for MySQL 5 and higher
|
||||
|
||||
\section3 QMYSQL Stored Procedure Support
|
||||
|
||||
MySQL 5 introduces stored procedure support at the SQL level, but no
|
||||
MySQL 5 has stored procedure support at the SQL level, but no
|
||||
API to control IN, OUT, and INOUT parameters. Therefore, parameters
|
||||
have to be set and read using SQL commands instead of QSqlQuery::bindValue().
|
||||
|
||||
@ -159,16 +170,32 @@
|
||||
|
||||
\section3 How to Build the QMYSQL Plugin on Windows
|
||||
|
||||
You need to get the MySQL installation files. Run \c SETUP.EXE and
|
||||
choose "Custom Install". Install the "Libs & Include Files" Module.
|
||||
Build the plugin as follows (here it is assumed that MySQL is
|
||||
installed in \c{C:\MySQL}):
|
||||
You need to get the MySQL installation files (e.g.
|
||||
\e{mysql-installer-web-community-8.0.18.0.msi}). Run the installer,
|
||||
select custom installation and install the MySQL C Connector
|
||||
which matches your Qt installation (x86 or x64).
|
||||
After installation make sure that the needed files are there:
|
||||
\list
|
||||
\li \c {<MySQL dir>/lib/libmysql.lib}
|
||||
\li \c {<MySQL dir>/lib/libmysql.dll}
|
||||
\li \c {<MySQL dir>/include/mysql.h}
|
||||
\endlist
|
||||
|
||||
Build the plugin as follows (here it is assumed that the MySQL
|
||||
C Connector is installed in
|
||||
\c{C:/Program Files/MySQL/MySQL Connector C 6.1}):
|
||||
|
||||
\snippet code/doc_src_sql-driver.qdoc 5
|
||||
|
||||
If you are not using a Microsoft compiler, replace \c nmake with \c
|
||||
mingw32-make in the line above.
|
||||
|
||||
When you distribute your application, remember to include libmysql.dll
|
||||
in your installation package. It must be placed in the same folder
|
||||
as the application executable. libmysql.dll additionally needs the
|
||||
MSVC runtime libraries which can be installed with vcredist.exe
|
||||
(\l {https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads}(vcredist.exe)
|
||||
|
||||
\target QOCI
|
||||
\section2 QOCI for the Oracle Call Interface (OCI)
|
||||
|
||||
@ -398,11 +425,6 @@
|
||||
|
||||
\snippet code/doc_src_sql-driver.qdoc 40
|
||||
|
||||
\section3 QPSQL BLOB Support
|
||||
|
||||
Binary Large Objects are supported through the \c BYTEA field type in
|
||||
PostgreSQL server versions >= 7.1.
|
||||
|
||||
\section3 QPSQL Forward-only query support
|
||||
|
||||
To use forward-only queries, you must build the QPSQL plugin with
|
||||
@ -463,6 +485,10 @@
|
||||
Users of MinGW may wish to consult the following online document:
|
||||
\l{http://www.postgresql.org/docs/current/static/installation-platform-notes.html#INSTALLATION-NOTES-MINGW}{PostgreSQL MinGW/Native Windows}.
|
||||
|
||||
When you distribute your application, remember to include libpq.dll
|
||||
in your installation package. It must be placed in the same folder
|
||||
as the application executable.
|
||||
|
||||
\target QTDS
|
||||
\section2 QTDS for Sybase Adaptive Server
|
||||
|
||||
|
@ -95,7 +95,7 @@ template<> inline char *toString(const QByteArray &ba)
|
||||
template<> inline char *toString(const QBitArray &ba)
|
||||
{
|
||||
qsizetype size = ba.size();
|
||||
char *str = static_cast<char *>(malloc(size + 1));
|
||||
char *str = new char[size + 1];
|
||||
for (qsizetype i = 0; i < size; ++i)
|
||||
str[i] = "01"[ba.testBit(i)];
|
||||
str[size] = '\0';
|
||||
|
@ -1717,17 +1717,18 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
|
||||
qmlImportScanner += QLatin1String(" -qrcFiles");
|
||||
for (const QString &qrcFile : options->qrcFiles)
|
||||
qmlImportScanner += QLatin1Char(' ') + shellQuote(qrcFile);
|
||||
} else {
|
||||
if (rootPath.isEmpty())
|
||||
rootPath = QFileInfo(options->inputFileName).absolutePath();
|
||||
else
|
||||
rootPath = QFileInfo(rootPath).absoluteFilePath();
|
||||
|
||||
if (!rootPath.endsWith(QLatin1Char('/')))
|
||||
rootPath += QLatin1Char('/');
|
||||
qmlImportScanner += QLatin1String(" -rootPath %1").arg(shellQuote(rootPath));
|
||||
}
|
||||
|
||||
if (rootPath.isEmpty())
|
||||
rootPath = QFileInfo(options->inputFileName).absolutePath();
|
||||
else
|
||||
rootPath = QFileInfo(rootPath).absoluteFilePath();
|
||||
|
||||
if (!rootPath.endsWith(QLatin1Char('/')))
|
||||
rootPath += QLatin1Char('/');
|
||||
|
||||
qmlImportScanner += QLatin1String(" -rootPath %1").arg(shellQuote(rootPath));
|
||||
|
||||
QStringList importPaths;
|
||||
importPaths += shellQuote(options->qtInstallDirectory + QLatin1String("/qml"));
|
||||
if (!rootPath.isEmpty())
|
||||
|
@ -1478,13 +1478,19 @@ bool RCCResourceLibrary::writeInitializer()
|
||||
writeString(" return 1;\n");
|
||||
writeString("}\n\n");
|
||||
|
||||
writeByteArray(
|
||||
"namespace {\n"
|
||||
" struct initializer {\n"
|
||||
" initializer() { QT_RCC_MANGLE_NAMESPACE(" + initResources + ")(); }\n"
|
||||
" ~initializer() { QT_RCC_MANGLE_NAMESPACE(" + cleanResources + ")(); }\n"
|
||||
" } dummy;\n"
|
||||
"}\n");
|
||||
|
||||
writeString("namespace {\n"
|
||||
" struct initializer {\n");
|
||||
|
||||
if (m_useNameSpace) {
|
||||
writeByteArray(" initializer() { QT_RCC_MANGLE_NAMESPACE(" + initResources + ")(); }\n"
|
||||
" ~initializer() { QT_RCC_MANGLE_NAMESPACE(" + cleanResources + ")(); }\n");
|
||||
} else {
|
||||
writeByteArray(" initializer() { " + initResources + "(); }\n"
|
||||
" ~initializer() { " + cleanResources + "(); }\n");
|
||||
}
|
||||
writeString(" } dummy;\n"
|
||||
"}\n");
|
||||
|
||||
} else if (m_format == Binary) {
|
||||
int i = 4;
|
||||
|
@ -146,13 +146,13 @@ dialog.exec();
|
||||
//! [14]
|
||||
|
||||
//! [15]
|
||||
auto fileOpenCompleted = [](const QString &fileName, const QByteArray &fileContent) {
|
||||
auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) {
|
||||
if (fileName.isEmpty()) {
|
||||
// No file was selected
|
||||
} else {
|
||||
// Use fileName and fileContent
|
||||
}
|
||||
}
|
||||
};
|
||||
QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady);
|
||||
//! [15]
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <qvariant.h>
|
||||
#include <QtCore/private/qvariant_p.h>
|
||||
#include <qbitarray.h>
|
||||
#include <qbytearraylist.h>
|
||||
#include <qdatetime.h>
|
||||
@ -276,7 +277,8 @@ private slots:
|
||||
void nullConvert();
|
||||
|
||||
void accessSequentialContainerKey();
|
||||
|
||||
void shouldDeleteVariantDataWorksForSequential();
|
||||
void shouldDeleteVariantDataWorksForAssociative();
|
||||
void fromStdVariant();
|
||||
void qt4UuidDataStream();
|
||||
|
||||
@ -4990,6 +4992,99 @@ void tst_QVariant::accessSequentialContainerKey()
|
||||
QCOMPARE(nameResult, QStringLiteral("Seven"));
|
||||
}
|
||||
|
||||
void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
|
||||
{
|
||||
QCOMPARE(instanceCount, 0);
|
||||
{
|
||||
QtMetaTypePrivate::QSequentialIterableImpl iterator {};
|
||||
iterator._iteratorCapabilities = QtMetaTypePrivate::RandomAccessCapability |
|
||||
QtMetaTypePrivate::BiDirectionalCapability |
|
||||
QtMetaTypePrivate::ForwardCapability;
|
||||
iterator._metaType_flags = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||
|
||||
iterator._size = [](const void *) {return 1;};
|
||||
iterator._metaType_id = qMetaTypeId<MyType>();
|
||||
iterator._moveToBegin = [](const void *, void **) {};
|
||||
iterator._moveToEnd = [](const void *, void **) {};
|
||||
iterator._advance = [](void **, int) {};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._at = [](const void *, int ) -> void const * {
|
||||
MyType mytype {1, "eins"};
|
||||
return QMetaType::create(qMetaTypeId<MyType>(), &mytype);
|
||||
};
|
||||
iterator._get = [](void * const *, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||
MyType mytype {2, "zwei"};
|
||||
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||
};
|
||||
QSequentialIterable iterable {iterator};
|
||||
QVariant value1 = iterable.at(0);
|
||||
QVERIFY(value1.canConvert<MyType>());
|
||||
QCOMPARE(value1.value<MyType>().number, 1);
|
||||
QVariant value2 = *iterable.begin();
|
||||
QVERIFY(value2.canConvert<MyType>());
|
||||
QCOMPARE(value2.value<MyType>().number, 2);
|
||||
}
|
||||
QCOMPARE(instanceCount, 0);
|
||||
}
|
||||
|
||||
void tst_QVariant::shouldDeleteVariantDataWorksForAssociative()
|
||||
{
|
||||
QCOMPARE(instanceCount, 0);
|
||||
{
|
||||
QtMetaTypePrivate::QAssociativeIterableImpl iterator {};
|
||||
iterator._metaType_flags_key = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||
iterator._metaType_flags_value = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||
|
||||
iterator._size = [](const void *) {return 1;};
|
||||
iterator._metaType_id_value = qMetaTypeId<MyType>();
|
||||
iterator._metaType_id_key = qMetaTypeId<MyType>();
|
||||
iterator._begin = [](const void *, void **) {};
|
||||
iterator._end = [](const void *, void **) {};
|
||||
iterator._advance = [](void **, int) {};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
|
||||
iterator._destroyIter = [](void **){};
|
||||
iterator._find = [](const void *, const void *, void **iterator ) -> void {
|
||||
(*iterator) = reinterpret_cast<void *>(quintptr(42));
|
||||
};
|
||||
iterator._getKey = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||
MyType mytype {1, "key"};
|
||||
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||
mytype.number = 42;
|
||||
mytype.text = "find_key";
|
||||
}
|
||||
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||
};
|
||||
iterator._getValue = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||
MyType mytype {2, "value"};
|
||||
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||
mytype.number = 42;
|
||||
mytype.text = "find_value";
|
||||
}
|
||||
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||
};
|
||||
QAssociativeIterable iterable {iterator};
|
||||
auto it = iterable.begin();
|
||||
QVariant value1 = it.key();
|
||||
QVERIFY(value1.canConvert<MyType>());
|
||||
QCOMPARE(value1.value<MyType>().number, 1);
|
||||
QCOMPARE(value1.value<MyType>().text, "key");
|
||||
QVariant value2 = it.value();
|
||||
QVERIFY(value2.canConvert<MyType>());
|
||||
QCOMPARE(value2.value<MyType>().number, 2);
|
||||
auto findIt = iterable.find(QVariant::fromValue(MyType {}));
|
||||
value1 = findIt.key();
|
||||
QCOMPARE(value1.value<MyType>().number, 42);
|
||||
QCOMPARE(value1.value<MyType>().text, "find_key");
|
||||
value2 = findIt.value();
|
||||
QCOMPARE(value2.value<MyType>().number, 42);
|
||||
QCOMPARE(value2.value<MyType>().text, "find_value");
|
||||
}
|
||||
QCOMPARE(instanceCount, 0);
|
||||
}
|
||||
|
||||
void tst_QVariant::fromStdVariant()
|
||||
{
|
||||
#if __has_include(<variant>) && __cplusplus >= 201703L
|
||||
|
@ -2213,8 +2213,46 @@ void tst_QDateTime::fromStringDateFormat_data()
|
||||
QTest::newRow("trailing space") // QTBUG-80445
|
||||
<< QString("2000-01-02 03:04:05.678 ")
|
||||
<< Qt::ISODate << QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5, 678));
|
||||
|
||||
// Invalid spaces (but keeping field widths correct):
|
||||
QTest::newRow("space before millis")
|
||||
<< QString("2000-01-02 03:04:05. 678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after seconds")
|
||||
<< QString("2000-01-02 03:04:5 .678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space before seconds")
|
||||
<< QString("2000-01-02 03:04: 5.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after minutes")
|
||||
<< QString("2000-01-02 03:4 :05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space before minutes")
|
||||
<< QString("2000-01-02 03: 4:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after hour")
|
||||
<< QString("2000-01-02 3 :04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space before hour")
|
||||
<< QString("2000-01-02 3:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after day")
|
||||
<< QString("2000-01-2 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space before day")
|
||||
<< QString("2000-01- 2 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after month")
|
||||
<< QString("2000-1 -02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space before month")
|
||||
<< QString("2000- 1-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("space after year")
|
||||
<< QString("200 -01-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
|
||||
// Spaces as separators:
|
||||
QTest::newRow("sec-milli space")
|
||||
<< QString("2000-01-02 03:04:05 678") << Qt::ISODate
|
||||
// Should be invalid, but we ignore trailing cruft (in some cases)
|
||||
<< QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5));
|
||||
QTest::newRow("min-sec space")
|
||||
<< QString("2000-01-02 03:04 05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("hour-min space")
|
||||
<< QString("2000-01-02 03 04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("mon-day space")
|
||||
<< QString("2000-01 02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
QTest::newRow("year-mon space")
|
||||
<< QString("2000 01-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||
|
||||
// Normal usage:
|
||||
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
|
||||
|
Loading…
Reference in New Issue
Block a user