Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"

This commit is contained in:
Qt Forward Merge Bot 2020-01-06 01:00:08 +01:00 committed by Fabian Kosmale
commit 68c30e372b
39 changed files with 511 additions and 138 deletions

View File

@ -85,8 +85,8 @@
\snippet widgets/styles/norwegianwoodstyle.cpp 0
The \c polish() function is reimplemented from QStyle. It takes a
QPalette as a reference and adapts the palette to fit the style.
The \c standardPalette() function is reimplemented from QStyle.
It returns a QPalette with the style's preferred colors and textures.
Most styles don't need to reimplement that function. The
Norwegian Wood style reimplements it to set a "wooden" palette.
@ -381,7 +381,7 @@
a certain \l{QPalette::ColorRole}{color role}, for all three
\l{QPalette::ColorGroup}{color groups} (active, disabled,
inactive). We used it to initialize the Norwegian Wood palette in
\c polish(QPalette &).
\c standardPalette.
\snippet widgets/styles/norwegianwoodstyle.cpp 39
\snippet widgets/styles/norwegianwoodstyle.cpp 40
@ -444,10 +444,6 @@
current style's \l{QStyle::standardPalette()}{standard palette}
is used; otherwise, the system's default palette is honored.
For the Norwegian Wood style, this makes no difference because we
always override the palette with our own palette in \c
NorwegianWoodStyle::polish().
\snippet widgets/styles/widgetgallery.cpp 9
\snippet widgets/styles/widgetgallery.cpp 10

View File

@ -62,8 +62,9 @@ NorwegianWoodStyle::NorwegianWoodStyle() :
}
//! [0]
void NorwegianWoodStyle::polish(QPalette &palette)
QPalette NorwegianWoodStyle::standardPalette() const
{
if (!m_standardPalette.isBrushSet(QPalette::Disabled, QPalette::Mid)) {
QColor brown(212, 140, 95);
QColor beige(236, 182, 120);
QColor slightlyOpaqueBlack(0, 0, 0, 63);
@ -77,10 +78,10 @@ void NorwegianWoodStyle::polish(QPalette &palette)
painter.setPen(Qt::NoPen);
painter.fillRect(midImage.rect(), slightlyOpaqueBlack);
painter.end();
//! [0]
//! [0]
//! [1]
palette = QPalette(brown);
//! [1]
QPalette palette(brown);
palette.setBrush(QPalette::BrightText, Qt::white);
palette.setBrush(QPalette::Base, beige);
@ -98,6 +99,11 @@ void NorwegianWoodStyle::polish(QPalette &palette)
palette.setBrush(QPalette::Disabled, QPalette::Base, brush);
palette.setBrush(QPalette::Disabled, QPalette::Button, brush);
palette.setBrush(QPalette::Disabled, QPalette::Mid, brush);
m_standardPalette = palette;
}
return m_standardPalette;
}
//! [1]

View File

@ -66,7 +66,8 @@ class NorwegianWoodStyle : public QProxyStyle
public:
NorwegianWoodStyle();
void polish(QPalette &palette) override;
QPalette standardPalette() const override;
void polish(QWidget *widget) override;
void unpolish(QWidget *widget) override;
int pixelMetric(PixelMetric metric, const QStyleOption *option,
@ -82,6 +83,7 @@ private:
static void setTexture(QPalette &palette, QPalette::ColorRole role,
const QImage &image);
static QPainterPath roundRectPath(const QRect &rect);
mutable QPalette m_standardPalette;
};
//! [0]

View File

@ -41,10 +41,9 @@ build_pass {
INSTALLS *= target
}
} else {
QMAKE_EXTRA_TARGETS *= aab apk apk_install_target
android-build-distclean.commands = \
$$QMAKE_DEL_TREE $$shell_quote($$shell_path($$OUT_PWD/android-build))
QMAKE_EXTRA_TARGETS *= android-build-distclean
CLEAN_DEPS += android-build-distclean
}
QMAKE_EXTRA_TARGETS *= aab apk apk_install_target

View File

@ -26,9 +26,9 @@ QMAKE_EXTRA_COMPILERS += dumpcpp_impl
!build_pass:have_target:!contains(TEMPLATE, vc.*) {
for(tlb, TYPELIBS) {
tlbCopy = $$replace(tlb, \", )
hdr = $$basename(tlb)
hdr = $$basename(tlbCopy)
hdr = $$section(hdr, ., 0, -2)
tmp_command = $$QMAKE_DUMPCPP $$system_quote($$absolute_path($$tlb, $$_PRO_FILE_PWD_)) \
tmp_command = $$QMAKE_DUMPCPP $$system_quote($$absolute_path($$tlbCopy, $$_PRO_FILE_PWD_)) \
-o $$system_quote($$OUT_PWD/$$hdr)
qaxcontainer_compat: tmp_command += -compat
!exists($$OUT_PWD/$${hdr}.h): system($$tmp_command)

View File

@ -0,0 +1,31 @@
From 7905740b8e79479298e83d8e559fc49b46cf980e Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.shaw@qt.io>
Date: Thu, 19 Dec 2019 21:59:09 +0100
Subject: [PATCH] Fix CVE-2019-19242 in SQLite
Change-Id: I78a72a574da5cf3503950afe47146ae6424f00c6
---
src/3rdparty/sqlite/sqlite3.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index bd647ca1c2..d3e0c065b6 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -101055,7 +101055,12 @@ expr_code_doover:
** constant.
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
- int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
+ int aff;
+ if( pExpr->y.pTab ){
+ aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
+ }else{
+ aff = pExpr->affExpr;
+ }
if( aff>SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
--
2.21.0 (Apple Git-122.2)

View File

@ -0,0 +1,95 @@
From 11a2f4647b67494fb731a6fd793f1b28074631d3 Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.shaw@qt.io>
Date: Thu, 19 Dec 2019 22:31:15 +0100
Subject: [PATCH] Fix CVE-2019-19603 in SQLite
This includes the patch needed to fix this CVE and a supporting one to
include a new function added that it depends on.
Task-number: QTBUG-80903
Change-Id: Ic7639d50c89a3ee7d45426588c3ab0efd0eebb72
---
src/3rdparty/sqlite/sqlite3.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index d3e0c065b6..a430554db7 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -19519,6 +19519,12 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
+#else
+# define sqlite3ShadowTableName(A,B) 0
+#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -108483,6 +108489,22 @@ SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){
return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
}
+/*
+ ** Return TRUE if shadow tables should be read-only in the current
+ ** context.
+ */
+int sqlite3ReadOnlyShadowTables(sqlite3 *db){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( (db->flags & SQLITE_Defensive)!=0
+ && db->pVtabCtx==0
+ && db->nVdbeExec==0
+ ){
+ return 1;
+ }
+#endif
+ return 0;
+}
+
/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
@@ -108516,8 +108538,8 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(
}
}
}else{
- if( pParse->nested==0
- && 0==sqlite3StrNICmp(zName, "sqlite_", 7)
+ if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
+ || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
zName);
@@ -109662,7 +109684,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
-static int isShadowTableName(sqlite3 *db, char *zName){
+int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
Module *pMod; /* Module for the virtual table */
@@ -109680,8 +109702,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){
if( pMod->pModule->xShadowName==0 ) return 0;
return pMod->pModule->xShadowName(zTail+1);
}
-#else
-# define isShadowTableName(x,y) 0
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
/*
@@ -109723,7 +109743,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
- if( pSelect==0 && isShadowTableName(db, p->zName) ){
+ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
p->tabFlags |= TF_Shadow;
}
--
2.21.0 (Apple Git-122.2)

View File

@ -0,0 +1,29 @@
From a83bbce4d6f31d93ea4d2a681aa52c148f148e26 Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.shaw@qt.io>
Date: Thu, 2 Jan 2020 09:07:08 +0100
Subject: [PATCH] Fix CVE-2019-19646 in SQLite
Task-number: QTBUG-81020
Change-Id: I7176db20d4a44b1fb443a6108675f719e9643343
---
src/3rdparty/sqlite/sqlite3.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 57e61b8313..980a149b1a 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -123765,7 +123765,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ }
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
--
2.21.0 (Apple Git-122.2)

View File

@ -0,0 +1,83 @@
From 78c972eec5bab03a408b8ba1373572bcfe2db630 Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.shaw@qt.io>
Date: Thu, 2 Jan 2020 08:47:23 +0100
Subject: [PATCH] Fix CVE-2019-19645 in SQLite
Task-number: QTBUG-81020
Change-Id: I58b1dd9e7a90ba998c3af7f25a4627d8bdd70970
---
src/3rdparty/sqlite/sqlite3.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index d3e0c065b6..57e61b8313 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -17946,6 +17946,7 @@ struct Select {
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
#define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */
+#define SF_View 0x0200000 /* SELECT statement is a view */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -103920,6 +103921,7 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
+ if( p->selFlags & SF_View ) return WRC_Prune;
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
@@ -104024,6 +104026,7 @@ static void renameWalkWith(Walker *pWalker, Select *pSelect){
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
+ if( p->selFlags & SF_View ) return WRC_Prune;
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -104489,8 +104492,9 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect;
if( pSelect ){
+ pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK;
- sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
+ sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
if( rc==SQLITE_OK ){
sqlite3WalkSelect(&sWalker, pSelect);
@@ -104602,6 +104606,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
+ if( pSelect->selFlags & SF_View ) return WRC_Prune;
if( pSrc==0 ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
@@ -104681,10 +104686,13 @@ static void renameTableFunc(
if( pTab->pSelect ){
if( isLegacy==0 ){
+ Select *pSelect = pTab->pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
+ assert( pSelect->selFlags & SF_View );
+ pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
@@ -109994,6 +110002,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
+ pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){
p->pSelect = pSelect;
pSelect = 0;
--
2.21.0 (Apple Git-122.2)

View File

@ -17946,6 +17946,7 @@ struct Select {
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
#define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */
#define SF_View 0x0200000 /* SELECT statement is a view */
/*
** The results of a SELECT can be distributed in several ways, as defined
@ -19519,6 +19520,12 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
#else
# define sqlite3ShadowTableName(A,B) 0
#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@ -101055,7 +101062,12 @@ expr_code_doover:
** constant.
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
int aff;
if( pExpr->y.pTab ){
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
aff = pExpr->affExpr;
}
if( aff>SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
@ -103915,6 +103927,7 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( p->selFlags & SF_View ) return WRC_Prune;
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
@ -104019,6 +104032,7 @@ static void renameWalkWith(Walker *pWalker, Select *pSelect){
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
if( p->selFlags & SF_View ) return WRC_Prune;
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@ -104484,8 +104498,9 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect;
if( pSelect ){
pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
if( rc==SQLITE_OK ){
sqlite3WalkSelect(&sWalker, pSelect);
@ -104597,6 +104612,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSelect->selFlags & SF_View ) return WRC_Prune;
if( pSrc==0 ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
@ -104676,10 +104692,13 @@ static void renameTableFunc(
if( pTab->pSelect ){
if( isLegacy==0 ){
Select *pSelect = pTab->pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View );
pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
@ -108478,6 +108497,22 @@ SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){
return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
}
/*
** Return TRUE if shadow tables should be read-only in the current
** context.
*/
int sqlite3ReadOnlyShadowTables(sqlite3 *db){
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( (db->flags & SQLITE_Defensive)!=0
&& db->pVtabCtx==0
&& db->nVdbeExec==0
){
return 1;
}
#endif
return 0;
}
/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
@ -108511,8 +108546,8 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(
}
}
}else{
if( pParse->nested==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7)
if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
|| (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
zName);
@ -109657,7 +109692,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
static int isShadowTableName(sqlite3 *db, char *zName){
int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
Module *pMod; /* Module for the virtual table */
@ -109675,8 +109710,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){
if( pMod->pModule->xShadowName==0 ) return 0;
return pMod->pModule->xShadowName(zTail+1);
}
#else
# define isShadowTableName(x,y) 0
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
/*
@ -109718,7 +109751,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
if( pSelect==0 && isShadowTableName(db, p->zName) ){
if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
p->tabFlags |= TF_Shadow;
}
@ -109989,6 +110022,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){
p->pSelect = pSelect;
pSelect = 0;
@ -123751,7 +123785,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);

View File

@ -109,7 +109,7 @@ QT_BEGIN_NAMESPACE
/*!
\internal
\since 5.14
bool qfloat16::isInf() const noexcept
\fn bool qfloat16::isInf() const noexcept
Tests whether this \c qfloat16 value is an infinity.
@ -119,7 +119,7 @@ QT_BEGIN_NAMESPACE
/*!
\internal
\since 5.14
bool qfloat16::isNaN() const noexcept
\fn bool qfloat16::isNaN() const noexcept
Tests whether this \c qfloat16 value is "not a number".
@ -128,7 +128,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.14
bool qfloat16::isNormal() const noexcept
\fn bool qfloat16::isNormal() const noexcept
Tests whether this \c qfloat16 value is finite and in normal form.
@ -138,7 +138,7 @@ QT_BEGIN_NAMESPACE
/*!
\internal
\since 5.14
bool qfloat16::isFinite() const noexcept
\fn bool qfloat16::isFinite() const noexcept
Tests whether this \c qfloat16 value is finite.

View File

@ -4600,7 +4600,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
It works exactly like the Q_NAMESPACE macro. However, the external
\c{staticMetaObject} variable that gets defined in the namespace
is declared with the supplied \c{EXPORT_MACRO} qualifier. This is
is declared with the supplied \a EXPORT_MACRO qualifier. This is
useful if the object needs to be exported from a dynamic library.
\sa Q_NAMESPACE, {Creating Shared Libraries}

View File

@ -803,7 +803,8 @@ namespace QtPrivate {
static QVariantList invoke(const QVariant &v)
{
const int typeId = v.userType();
if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() ||
(QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantList>()))) {
QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
QVariantList l;
l.reserve(iter.size());
@ -820,7 +821,7 @@ namespace QtPrivate {
static QVariantHash invoke(const QVariant &v)
{
const int typeId = v.userType();
if (typeId == qMetaTypeId<QVariantMap>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
if (typeId == qMetaTypeId<QVariantMap>() || ((QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantHash>()))) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantHash l;
l.reserve(iter.size());
@ -837,7 +838,7 @@ namespace QtPrivate {
static QVariantMap invoke(const QVariant &v)
{
const int typeId = v.userType();
if (typeId == qMetaTypeId<QVariantHash>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
if (typeId == qMetaTypeId<QVariantHash>() || (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantMap>()))) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
@ -853,12 +854,9 @@ namespace QtPrivate {
static QPair<QVariant, QVariant> invoke(const QVariant &v)
{
const int typeId = v.userType();
if (typeId == qMetaTypeId<QPair<QVariant, QVariant> >())
return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
QtMetaTypePrivate::QPairVariantInterfaceImpl pi = qvariant_cast<QtMetaTypePrivate::QPairVariantInterfaceImpl>(v);
if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()) && !(typeId == qMetaTypeId<QPair<QVariant, QVariant> >())) {
QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
const QtMetaTypePrivate::VariantData d1 = pi.first();
QVariant v1(d1.metaTypeId, d1.data, d1.flags);
if (d1.metaTypeId == qMetaTypeId<QVariant>())

View File

@ -174,7 +174,7 @@
\value Chewa Obsolete, please use Nyanja
\value Chickasaw Since Qt 5.14
\value Chiga
\value Chinese
\value Chinese (Mandarin)
\value Church
\value Chuvash
\value ClassicalMandaic Since Qt 5.1
@ -1201,14 +1201,6 @@
\sa toShort()
*/
/*!
\fn QString QLocale::toString(ushort i) const
\overload
\sa toUShort()
*/
/*!
\fn QString QLocale::toString(int i) const

View File

@ -2593,7 +2593,7 @@ uint qHash(long double key, uint seed) noexcept
\sa operator=()
*/
/*! \fn template <class Key, class T> template <class InputIterator> QMultiHash::QMultiHash(InputIterator begin, InputIterator end)
/*! \fn template <class Key, class T> template <class InputIterator> QMultiHash<Key, T>::QMultiHash(InputIterator begin, InputIterator end)
\since 5.14
Constructs a multi-hash with a copy of each of the elements in the iterator range

View File

@ -6048,7 +6048,11 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
// Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
blend_pixel(*dst, src, qRgbAvg(coverage));
} else if (!colorProfile) {
*dst = rgbBlend(*dst, src, coverage);
// First do naive blend with text-color
QRgb s = *dst;
blend_pixel(s, src);
// Then a naive blend with glyph shape
*dst = rgbBlend(*dst, s, coverage);
} else if (srcLinear.isOpaque()) {
rgbBlendPixel(dst, coverage, srcLinear, colorProfile);
} else {

View File

@ -2297,6 +2297,17 @@ QTextHtmlExporter::QTextHtmlExporter(const QTextDocument *_doc)
defaultCharFormat.clearProperty(QTextFormat::TextUnderlineStyle);
}
static QStringList resolvedFontFamilies(const QTextCharFormat &format)
{
QStringList fontFamilies = format.fontFamilies().toStringList();
const QString mainFontFamily = format.fontFamily();
if (!mainFontFamily.isEmpty() && !fontFamilies.startsWith(mainFontFamily)) {
fontFamilies.removeAll(mainFontFamily);
fontFamilies.prepend(mainFontFamily);
}
return fontFamilies;
}
/*!
Returns the document in HTML format. The conversion may not be
perfect, especially for complex documents, due to the limitations
@ -2325,11 +2336,7 @@ QString QTextHtmlExporter::toHtml(const QByteArray &encoding, ExportMode mode)
if (mode == ExportEntireDocument) {
html += QLatin1String(" style=\"");
QStringList fontFamilies = defaultCharFormat.fontFamilies().toStringList();
if (!fontFamilies.isEmpty())
emitFontFamily(fontFamilies);
else
emitFontFamily(defaultCharFormat.fontFamily());
emitFontFamily(resolvedFontFamilies(defaultCharFormat));
if (defaultCharFormat.hasProperty(QTextFormat::FontPointSize)) {
html += QLatin1String(" font-size:");
@ -2391,14 +2398,10 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
bool attributesEmitted = false;
{
const QStringList families = format.fontFamilies().toStringList();
const QString family = format.fontFamily();
if (!families.isEmpty() && families != defaultCharFormat.fontFamilies().toStringList()) {
const QStringList families = resolvedFontFamilies(format);
if (!families.isEmpty() && families != resolvedFontFamilies(defaultCharFormat)) {
emitFontFamily(families);
attributesEmitted = true;
} else if (!family.isEmpty() && family != defaultCharFormat.fontFamily()) {
emitFontFamily(family);
attributesEmitted = true;
}
}
@ -2661,20 +2664,6 @@ void QTextHtmlExporter::emitPageBreakPolicy(QTextFormat::PageBreakFlags policy)
html += QLatin1String(" page-break-after:always;");
}
void QTextHtmlExporter::emitFontFamily(const QString &family)
{
html += QLatin1String(" font-family:");
QLatin1String quote("\'");
if (family.contains(QLatin1Char('\'')))
quote = QLatin1String("&quot;");
html += quote;
html += family.toHtmlEscaped();
html += quote;
html += QLatin1Char(';');
}
void QTextHtmlExporter::emitFontFamily(const QStringList &families)
{
html += QLatin1String(" font-family:");

View File

@ -396,7 +396,6 @@ private:
void emitBorderStyle(QTextFrameFormat::BorderStyle style);
void emitPageBreakPolicy(QTextFormat::PageBreakFlags policy);
void emitFontFamily(const QString &family);
void emitFontFamily(const QStringList &families);
void emitBackgroundAttribute(const QTextFormat &format);

View File

@ -595,7 +595,7 @@ QHostInfo::QHostInfo(const QHostInfo &other)
}
/*!
\fn QHostInfo(QHostInfo &&other)
\fn QHostInfo::QHostInfo(QHostInfo &&other)
Move-constructs a new QHostInfo from \a other.

View File

@ -617,8 +617,10 @@ QImage QCALayerBackingStore::toImage() const
void QCALayerBackingStore::backingPropertiesChanged()
{
qCDebug(lcQpaBackingStore) << "Updating color space of existing buffers";
for (auto &buffer : m_buffers)
for (auto &buffer : m_buffers) {
if (buffer)
buffer->setColorSpace(colorSpace());
}
}
QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const

View File

@ -406,8 +406,6 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const
return QCoreTextFontEngine::fontSmoothingGamma();
case ShowShortcutsInContextMenus:
return QVariant(false);
// case CursorFlashTime:
// return 50000;
default: break;
}

View File

@ -89,9 +89,16 @@ QIOSurfaceGraphicsBuffer::~QIOSurfaceGraphicsBuffer()
void QIOSurfaceGraphicsBuffer::setColorSpace(QCFType<CGColorSpaceRef> colorSpace)
{
Q_ASSERT(colorSpace);
IOSurfaceSetValue(m_surface, CFSTR("IOSurfaceColorSpace"),
static const auto kIOSurfaceColorSpace = CFSTR("IOSurfaceColorSpace");
qCDebug(lcQpaIOSurface) << "Tagging" << this << "with color space" << colorSpace;
if (colorSpace) {
IOSurfaceSetValue(m_surface, kIOSurfaceColorSpace,
QCFType<CFPropertyListRef>(CGColorSpaceCopyPropertyList(colorSpace)));
} else {
IOSurfaceRemoveValue(m_surface, kIOSurfaceColorSpace);
}
}
const uchar *QIOSurfaceGraphicsBuffer::data() const

View File

@ -343,13 +343,6 @@ void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter)
pd = printer->d_func();
}
/*!
\fn int QAbstractPrintDialog::exec()
This virtual function is called to pop up the dialog. It must be
reimplemented in subclasses.
*/
/*!
\class QPrintDialog

View File

@ -243,7 +243,7 @@
Instead of \c Q_ASSERT, the \l QCOMPARE() or \l QVERIFY() macro variants
should be used. They cause the current test to report a failure and
terminate, but allow the remaining test functions to be executed and the
entire test program to terminate normally. \l Q_VERIFY2() even allows a
entire test program to terminate normally. \l QVERIFY2() even allows a
descriptive error message to be recorded in the test log.
\section1 Writing Reliable Tests

View File

@ -98,7 +98,7 @@
\snippet code/doc_src_qsignalspy.cpp 6
*/
/*! \fn QSignalSpy(const QObject *obj, const QMetaMethod &signal)
/*! \fn QSignalSpy::QSignalSpy(const QObject *obj, const QMetaMethod &signal)
\since 5.14
Constructs a new QSignalSpy that listens for emissions of the \a signal

View File

@ -731,7 +731,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
if (const DomProperty *picon = attributes.value(QLatin1String("icon")))
icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition
m_output << m_indent << parentWidget << language::derefPointer << "addTab("
<< varName << icon << ", " << "QString())" << language::eol;
<< varName << icon << ", " << language::emptyString << ')' << language::eol;
autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget
<< language::derefPointer << "setTabText(" << parentWidget
@ -1612,7 +1612,7 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
}
if (f->hasElementWeight() && f->elementWeight() > 0) {
m_output << m_indent << fontName << ".setWeight("
<< f->elementWeight() << ");" << Qt::endl;
<< f->elementWeight() << ")" << language::eol;
}
if (f->hasElementStrikeOut()) {
m_output << m_indent << fontName << ".setStrikeOut("
@ -2086,7 +2086,7 @@ void WriteInitialization::initializeComboBox(DomWidget *w)
m_output << iconValue << ", ";
if (needsTranslation(text->elementString())) {
m_output << "QString())" << language::eol;
m_output << language::emptyString << ')' << language::eol;
m_refreshOut << m_indent << varName << language::derefPointer
<< "setItemText(" << i << ", " << trCall(text->elementString())
<< ')' << language::eol;
@ -2288,7 +2288,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
if (str && str->text().isEmpty()) {
m_output << m_indent << varName << language::derefPointer
<< "headerItem()" << language::derefPointer << "setText("
<< i << ", QString())" << language::eol;
<< i << ", " << language::emptyString << ')' << language::eol;
}
}
}
@ -2372,9 +2372,11 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const auto &columns = w->elementColumn();
if (!columns.empty()) {
m_output << m_indent << "if (" << varName << language::derefPointer << "columnCount() < "
<< columns.size() << ")\n"
<< m_dindent << varName << language::derefPointer << "setColumnCount("
m_output << m_indent << "if (" << varName << language::derefPointer
<< "columnCount() < " << columns.size() << ')';
if (language::language() == Language::Python)
m_output << ':';
m_output << '\n' << m_dindent << varName << language::derefPointer << "setColumnCount("
<< columns.size() << ')' << language::eol;
}
@ -2400,8 +2402,11 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const auto &rows = w->elementRow();
if (!rows.isEmpty()) {
m_output << m_indent << "if (" << varName << language::derefPointer << "rowCount() < " << rows.size() << ")\n"
<< m_dindent << varName << language::derefPointer << "setRowCount("
m_output << m_indent << "if (" << varName << language::derefPointer
<< "rowCount() < " << rows.size() << ')';
if (language::language() == Language::Python)
m_output << ':';
m_output << '\n' << m_dindent << varName << language::derefPointer << "setRowCount("
<< rows.size() << ')' << language::eol;
}
@ -2451,10 +2456,8 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const
{
if (str.isEmpty()) {
return language::language() == Language::Cpp
? QLatin1String("QString()") : QLatin1String("\"\"");
}
if (str.isEmpty())
return language::emptyString;
QString result;
QTextStream ts(&result);

View File

@ -108,6 +108,10 @@ int runUic(int argc, char *argv[])
idBasedOption.setDescription(QStringLiteral("Use id based function for i18n"));
parser.addOption(idBasedOption);
QCommandLineOption fromImportsOption(QStringLiteral("from-imports"));
fromImportsOption.setDescription(QStringLiteral("Python: generate imports relative to '.'"));
parser.addOption(fromImportsOption);
parser.addPositionalArgument(QStringLiteral("[uifile]"), QStringLiteral("Input file (*.ui), otherwise stdin."));
parser.process(app);
@ -118,6 +122,7 @@ int runUic(int argc, char *argv[])
driver.option().headerProtection = !parser.isSet(noProtOption);
driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption);
driver.option().idBased = parser.isSet(idBasedOption);
driver.option().fromImports = parser.isSet(fromImportsOption);
driver.option().postfix = parser.value(postfixOption);
driver.option().translateFunction = parser.value(translateOption);
driver.option().includeFile = parser.value(includeOption);

View File

@ -45,6 +45,7 @@ struct Option
unsigned int limitXPM_LineLength : 1;
unsigned int implicitIncludes: 1;
unsigned int idBased: 1;
unsigned int fromImports: 1;
QString inputFile;
QString outputFile;
@ -65,6 +66,7 @@ struct Option
limitXPM_LineLength(0),
implicitIncludes(1),
idBased(0),
fromImports(0),
prefix(QLatin1String("Ui_"))
{ indent.fill(QLatin1Char(' '), 4); }

View File

@ -29,6 +29,7 @@
#include "pythonwriteimports.h"
#include <customwidgetsinfo.h>
#include <option.h>
#include <uic.h>
#include <ui4.h>
@ -46,6 +47,20 @@ from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont,
from PySide2.QtWidgets import *
)I";
// Change the name of a qrc file "dir/foo.qrc" file to the Python
// module name "foo_rc" according to project conventions.
static QString pythonResource(QString resource)
{
const int lastSlash = resource.lastIndexOf(QLatin1Char('/'));
if (lastSlash != -1)
resource.remove(0, lastSlash + 1);
if (resource.endsWith(QLatin1String(".qrc"))) {
resource.chop(4);
resource.append(QLatin1String("_rc"));
}
return resource;
}
namespace Python {
WriteImports::WriteImports(Uic *uic) : m_uic(uic)
@ -60,6 +75,23 @@ void WriteImports::acceptUI(DomUI *node)
TreeWalker::acceptCustomWidgets(customWidgets);
output << '\n';
}
if (auto resources = node->elementResources()) {
const auto includes = resources->elementInclude();
for (auto include : includes) {
if (include->hasAttributeLocation())
writeImport(pythonResource(include->attributeLocation()));
}
output << '\n';
}
}
void WriteImports::writeImport(const QString &module)
{
if (m_uic->option().fromImports)
m_uic->output() << "from . ";
m_uic->output() << "import " << module << '\n';
}
QString WriteImports::qtModuleOf(const DomCustomWidget *node) const

View File

@ -46,6 +46,7 @@ public:
void acceptCustomWidget(DomCustomWidget *node) override;
private:
void writeImport(const QString &module);
QString qtModuleOf(const DomCustomWidget *node) const;
Uic *const m_uic;

View File

@ -49,6 +49,7 @@ void setLanguage(Language l)
qualifier = QLatin1String("::");
self = QLatin1String(""); // for testing: change to "this->";
eol = QLatin1String(";\n");
emptyString = QLatin1String("QString()");
encoding = Encoding::Utf8;
break;
case Language::Python:
@ -59,6 +60,7 @@ void setLanguage(Language l)
qualifier = QLatin1String(".");
self = QLatin1String("self.");
eol = QLatin1String("\n");
emptyString = QLatin1String("\"\"");
encoding = Encoding::Unicode;
break;
}
@ -71,6 +73,7 @@ QString qtQualifier;
QString qualifier;
QString self;
QString eol;
QString emptyString;
QString cppQualifier = QLatin1String("::");
QString cppTrue = QLatin1String("true");

View File

@ -49,6 +49,7 @@ extern QString qtQualifier;
extern QString qualifier;
extern QString self;
extern QString eol;
extern QString emptyString;
extern QString cppQualifier;
extern QString cppTrue;

View File

@ -292,7 +292,8 @@ QList<QAction*> QActionGroup::actions() const
\brief Enable or disable the group exclusion checking
This is a convenience method that calls
setExclusionPolicy(ExclusionPolicy::Exclusive).
setExclusionPolicy(ExclusionPolicy::Exclusive) when \a b is true,
else setExclusionPolicy(QActionGroup::ExclusionPolicy::None).
\sa QActionGroup::exclusionPolicy
*/
@ -303,7 +304,7 @@ void QActionGroup::setExclusive(bool b)
}
/*!
\brief Returs true if the group is exclusive
\brief Returns true if the group is exclusive
The group is exclusive if the ExclusionPolicy is either Exclusive
or ExclusionOptional.

View File

@ -545,7 +545,7 @@ QShortcut::QShortcut(QWidget *parent)
match the \a key sequence. Depending on the ambiguity of the
event, the shortcut will call the \a member function, or the \a
ambiguousMember function, if the key press was in the shortcut's
\a context.
\a shortcutContext.
*/
QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
const char *member, const char *ambiguousMember,

View File

@ -3027,6 +3027,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
r = positionRect(w, subRule, subRule2, PseudoElement_ComboBoxArrow, r, opt->direction);
subRule2.drawRule(p, r);
} else {
rule.configurePalette(&cmbOpt.palette, QPalette::ButtonText, QPalette::Button);
cmbOpt.subControls = QStyle::SC_ComboBoxArrow;
QWindowsStyle::drawComplexControl(cc, &cmbOpt, p, w);
}

View File

@ -335,7 +335,6 @@ void QDateTimeEdit::setCalendar(QCalendar calendar)
/*!
\since 4.4
\property QDateTimeEdit::minimumDateTime
\brief the minimum datetime of the date time edit
Changing this property implicitly updates the \l minimumDate and \l
@ -637,8 +636,8 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
Note that these only constrain the date time edit's value on,
respectively, the \l minimumDate and \l maximumDate. When these date
properties do not coincide, times after \a maximumTime are allowed on dates
before \l maximumDate and times before \a minimumTime are allowed on dates
properties do not coincide, times after \a max are allowed on dates
before \l maximumDate and times before \a min are allowed on dates
after \l minimumDate.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 5
@ -649,7 +648,7 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
If either \a min or \a max is invalid, this function does nothing. This
function preserves the \l minimumDate and \l maximumDate properties. If those
properties coincide and max is \a less than \a min, \a min is used as \a max.
properties coincide and \a max is less than \a min, \a min is used as \a max.
\sa minimumTime, maximumTime, setDateTimeRange(), QTime::isValid()
*/

View File

@ -839,7 +839,8 @@ void QPlainTextEditPrivate::_q_textChanged()
placeholderVisible = !placeholderText.isEmpty()
&& q->document()->isEmpty()
&& q->firstVisibleBlock().layout()->preeditAreaText().isEmpty();
&& (!q->firstVisibleBlock().isValid() ||
q->firstVisibleBlock().layout()->preeditAreaText().isEmpty());
if (placeholderCurrentyVisible != placeholderVisible)
viewport->update();

View File

@ -282,6 +282,8 @@ private slots:
void fromStdVariant();
void qt4UuidDataStream();
void preferDirectConversionOverInterfaces();
private:
void dataStream_data(QDataStream::Version version);
void loadQVariantFromDataStream(QDataStream::Version version);
@ -5140,5 +5142,47 @@ void tst_QVariant::qt4UuidDataStream()
QCOMPARE(result.value<QUuid>(), source);
}
void tst_QVariant::preferDirectConversionOverInterfaces()
{
using namespace QtMetaTypePrivate;
bool calledCorrectConverter = false;
QMetaType::registerConverter<MyType, QSequentialIterableImpl>([](const MyType &) {
return QSequentialIterableImpl {};
});
QMetaType::registerConverter<MyType, QVariantList>([&calledCorrectConverter](const MyType &) {
calledCorrectConverter = true;
return QVariantList {};
});
QMetaType::registerConverter<MyType, QAssociativeIterableImpl>([](const MyType &) {
return QAssociativeIterableImpl {};
});
QMetaType::registerConverter<MyType, QVariantHash>([&calledCorrectConverter](const MyType &) {
calledCorrectConverter = true;
return QVariantHash {};
});
QMetaType::registerConverter<MyType, QVariantMap>([&calledCorrectConverter](const MyType &) {
calledCorrectConverter = true;
return QVariantMap {};
});
auto holder = QVariant::fromValue(MyType {});
QVERIFY(holder.canConvert<QSequentialIterableImpl>());
QVERIFY(holder.canConvert<QVariantList>());
QVERIFY(holder.canConvert<QAssociativeIterableImpl>());
QVERIFY(holder.canConvert<QVariantHash>());
QVERIFY(holder.canConvert<QVariantMap>());
holder.value<QVariantList>();
QVERIFY(calledCorrectConverter);
calledCorrectConverter = false;
holder.value<QVariantHash>();
QVERIFY(calledCorrectConverter);
calledCorrectConverter = false;
holder.value<QVariantMap>();
QVERIFY(calledCorrectConverter);
}
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"

View File

@ -194,6 +194,8 @@ private slots:
void fontTagFace();
void clearUndoRedoStacks();
void mergeFontFamilies();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@ -3585,6 +3587,25 @@ void tst_QTextDocument::fontTagFace()
}
}
void tst_QTextDocument::mergeFontFamilies()
{
QTextDocument td;
td.setHtml(QLatin1String(
"<html><body>"
"<span style=\" font-family:'MS Shell Dlg 2';\">Hello world</span>"
"</body></html>"));
QTextCharFormat newFormat;
newFormat.setFontFamily(QLatin1String("Jokerman"));
QTextCursor cursor = QTextCursor(&td);
cursor.setPosition(0);
cursor.setPosition(QByteArray("Hello World").length(), QTextCursor::KeepAnchor);
cursor.mergeCharFormat(newFormat);
QVERIFY(td.toHtml().contains(QLatin1String("font-family:'Jokerman','MS Shell Dlg 2';")));
}
void tst_QTextDocument::clearUndoRedoStacks()
{
QTextDocument doc;