summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-4.5.24
-rw-r--r--doc/src/qnamespace.qdoc2
-rw-r--r--doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp24
-rw-r--r--src/corelib/codecs/qfontlaocodec.cpp3
-rw-r--r--src/corelib/codecs/qiconvcodec.cpp15
-rw-r--r--src/corelib/codecs/qisciicodec.cpp6
-rw-r--r--src/corelib/codecs/qlatincodec.cpp6
-rw-r--r--src/corelib/codecs/qsimplecodec.cpp3
-rw-r--r--src/corelib/codecs/qtsciicodec.cpp3
-rw-r--r--src/corelib/codecs/qutfcodec.cpp3
-rw-r--r--src/corelib/global/qnamespace.h2
-rw-r--r--src/corelib/statemachine/qstate.cpp11
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp12
-rw-r--r--src/corelib/tools/qbytearray.cpp30
-rw-r--r--src/corelib/tools/qbytearray.h3
-rw-r--r--src/corelib/tools/qstring.cpp11
-rw-r--r--src/corelib/tools/qstring.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp301
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h17
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp4
-rw-r--r--src/gui/kernel/qapplication_x11.cpp48
-rw-r--r--src/gui/painting/qmatrix.cpp2
-rw-r--r--src/gui/painting/qmatrix.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp8
-rw-r--r--src/gui/painting/qstroker_p.h2
-rw-r--r--src/gui/painting/qtransform.cpp2
-rw-r--r--src/gui/painting/qtransform.h2
-rw-r--r--src/gui/widgets/qdockarealayout.cpp99
-rw-r--r--src/gui/widgets/qdockarealayout_p.h6
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp4
-rw-r--r--src/gui/widgets/qmenu.cpp6
-rw-r--r--src/gui/widgets/qplaintextedit.cpp11
-rw-r--r--src/gui/widgets/qtoolbararealayout.cpp4
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp5
-rw-r--r--src/network/access/qnetworkdiskcache.cpp14
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp3
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h21
-rw-r--r--src/sql/drivers/db2/qsql_db2.cpp91
-rw-r--r--src/sql/drivers/ibase/qsql_ibase.cpp52
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp3
-rw-r--r--src/sql/drivers/oci/qsql_oci.cpp2
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp1
-rw-r--r--src/sql/drivers/psql/qsql_psql.cpp32
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp18
-rw-r--r--src/sql/drivers/sqlite2/qsql_sqlite2.cpp2
-rw-r--r--src/sql/drivers/tds/qsql_tds.cpp21
-rw-r--r--src/sql/kernel/qsqlcachedresult.cpp13
-rw-r--r--src/sql/kernel/qsqlcachedresult_p.h1
-rw-r--r--src/sql/kernel/qsqlresult.cpp2
-rw-r--r--src/sql/models/qsqltablemodel.cpp20
-rw-r--r--src/svg/qsvggraphics.cpp5
-rw-r--r--src/svg/qsvggraphics_p.h5
-rw-r--r--src/svg/qsvghandler.cpp63
-rw-r--r--src/svg/qsvgstructure.cpp98
-rw-r--r--src/svg/qsvgstyle.cpp7
-rw-r--r--src/svg/qsvgstyle_p.h34
-rw-r--r--src/svg/qsvgtinydocument.cpp12
-rw-r--r--src/testlib/qtestlog.cpp2
-rw-r--r--tests/auto/qpainter/tst_qpainter.cpp21
-rw-r--r--tests/auto/qsqldatabase/tst_databases.h42
-rw-r--r--tests/auto/qsqldatabase/tst_qsqldatabase.cpp22
-rw-r--r--tests/auto/qsqldriver/qsqldriver.pro16
-rw-r--r--tests/auto/qsqldriver/tst_qsqldriver.cpp218
-rw-r--r--tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp455
-rw-r--r--tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp15
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp49
-rw-r--r--tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp272
-rw-r--r--tools/qdoc3/test/qt-build-docs.qdocconf1
-rw-r--r--tools/qdoc3/test/qt.qdocconf1
70 files changed, 1792 insertions, 509 deletions
diff --git a/dist/changes-4.5.2 b/dist/changes-4.5.2
index 91a7bef..163e476 100644
--- a/dist/changes-4.5.2
+++ b/dist/changes-4.5.2
@@ -55,6 +55,10 @@ General Improvements
Plugins (r41346, r43550, r43915, r43917, r43923)
Clipboard (r41360)
SVG (r43590, r43795)
+ * Backported various security fixes (r41262, r41568,
+ r41741, r41854, r42081, r42216, r42223, r42333,
+ r42365, r42532, r42533, r44010)
+
- QAbstractItemView
* [250754] Changing the font of the view did not update the size of the
diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc
index 8a24764..7e655b6 100644
--- a/doc/src/qnamespace.qdoc
+++ b/doc/src/qnamespace.qdoc
@@ -2687,7 +2687,7 @@
*/
/*!
- \enum Uninitialized
+ \enum Qt::Initialization
\internal
*/
diff --git a/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp b/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp
new file mode 100644
index 0000000..acd3938
--- /dev/null
+++ b/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp
@@ -0,0 +1,24 @@
+//! [0]
+QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
+diskCache->setCacheDirectory("cacheDir");
+manager->setCache(diskCache);
+//! [0]
+
+//! [1]
+// do a normal request (preferred from network, as this is the default)
+QNetworkRequest request(QUrl(QString("http://www.qtsoftware.com")));
+manager->get(request);
+
+// do a request preferred from cache
+QNetworkRequest request2(QUrl(QString("http://www.qtsoftware.com")));
+request2.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+manager->get(request2);
+//! [1]
+
+//! [2]
+void replyFinished(QNetworkReply *reply) {
+ QVariant fromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute);
+ qDebug() << "page from cache?" << fromCache.toBool();
+}
+//! [2]
diff --git a/src/corelib/codecs/qfontlaocodec.cpp b/src/corelib/codecs/qfontlaocodec.cpp
index 85017e0..6dd87de 100644
--- a/src/corelib/codecs/qfontlaocodec.cpp
+++ b/src/corelib/codecs/qfontlaocodec.cpp
@@ -97,8 +97,7 @@ QString QFontLaoCodec::convertToUnicode(const char *, int, ConverterState *) con
QByteArray QFontLaoCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *) const
{
- QByteArray rstring;
- rstring.resize(len);
+ QByteArray rstring(len, Qt::Uninitialized);
uchar *rdata = (uchar *) rstring.data();
const QChar *sdata = uc;
int i = 0;
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp
index 6b9c77b..1bf76ea 100644
--- a/src/corelib/codecs/qiconvcodec.cpp
+++ b/src/corelib/codecs/qiconvcodec.cpp
@@ -225,11 +225,10 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
char *inBytes = const_cast<char *>(chars);
#endif
- QByteArray in;
if (remainingCount) {
// we have to prepend the remaining bytes from the previous conversion
inBytesLeft += remainingCount;
- in.resize(inBytesLeft);
+ QByteArray in(inBytesLeft, Qt::Uninitialized);
inBytes = in.data();
memcpy(in.data(), remainingBuffer, remainingCount);
@@ -238,9 +237,8 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
remainingCount = 0;
}
- QByteArray ba;
size_t outBytesLeft = len * 2 + 2;
- ba.resize(outBytesLeft);
+ QByteArray ba(outBytesLeft, Qt::Uninitialized);
char *outBytes = ba.data();
do {
size_t ret = iconv(state->cd, &inBytes, &inBytesLeft, &outBytes, &outBytesLeft);
@@ -328,8 +326,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
state = new IconvState(QIconvCodec::createIconv_t(0, UTF16));
if (state->cd != reinterpret_cast<iconv_t>(-1)) {
size_t outBytesLeft = len + 3; // +3 for the BOM
- QByteArray ba;
- ba.resize(outBytesLeft);
+ QByteArray ba(outBytesLeft, Qt::Uninitialized);
outBytes = ba.data();
#if !defined(NO_BOM)
@@ -358,18 +355,16 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
}
size_t outBytesLeft = len;
- QByteArray ba;
- ba.resize(outBytesLeft);
+ QByteArray ba(outBytesLeft, Qt::Uninitialized);
outBytes = ba.data();
// now feed iconv() the real data
inBytes = const_cast<char *>(reinterpret_cast<const char *>(uc));
inBytesLeft = len * sizeof(QChar);
- QByteArray in;
if (convState && convState->remainingChars) {
// we have one surrogate char to be prepended
- in.resize(sizeof(QChar) + len);
+ QByteArray in(sizeof(QChar) + len, Qt::Uninitialized);
inBytes = in.data();
QChar remaining = convState->state_data[0];
diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp
index a33fd0d..c054313 100644
--- a/src/corelib/codecs/qisciicodec.cpp
+++ b/src/corelib/codecs/qisciicodec.cpp
@@ -187,8 +187,7 @@ QByteArray QIsciiCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
}
int invalid = 0;
- QByteArray result;
- result.resize(2*len); //worst case
+ QByteArray result(2 * len, Qt::Uninitialized); //worst case
uchar *ch = reinterpret_cast<uchar *>(result.data());
@@ -250,8 +249,7 @@ QString QIsciiCodec::convertToUnicode(const char* chars, int len, ConverterState
halant = state->state_data[0];
}
- QString result;
- result.resize(len);
+ QString result(len, Qt::Uninitialized);
QChar *uc = result.data();
const int base = codecs[idx].base;
diff --git a/src/corelib/codecs/qlatincodec.cpp b/src/corelib/codecs/qlatincodec.cpp
index 176ae97..9113555 100644
--- a/src/corelib/codecs/qlatincodec.cpp
+++ b/src/corelib/codecs/qlatincodec.cpp
@@ -62,8 +62,7 @@ QString QLatin1Codec::convertToUnicode(const char *chars, int len, ConverterStat
QByteArray QLatin1Codec::convertFromUnicode(const QChar *ch, int len, ConverterState *state) const
{
const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
- QByteArray r;
- r.resize(len);
+ QByteArray r(len, Qt::Uninitialized);
char *d = r.data();
int invalid = 0;
for (int i = 0; i < len; ++i) {
@@ -151,8 +150,7 @@ QString QLatin15Codec::convertToUnicode(const char* chars, int len, ConverterSta
QByteArray QLatin15Codec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
{
const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
- QByteArray r;
- r.resize(length);
+ QByteArray r(length, Qt::Uninitialized);
char *d = r.data();
int invalid = 0;
for (int i = 0; i < length; ++i) {
diff --git a/src/corelib/codecs/qsimplecodec.cpp b/src/corelib/codecs/qsimplecodec.cpp
index aa7521d..0d14f67 100644
--- a/src/corelib/codecs/qsimplecodec.cpp
+++ b/src/corelib/codecs/qsimplecodec.cpp
@@ -676,8 +676,7 @@ QByteArray QSimpleTextCodec::convertFromUnicode(const QChar *in, int length, Con
delete tmp;
}
- QByteArray r;
- r.resize(length);
+ QByteArray r(length, Qt::Uninitialized);
int i = length;
int u;
const QChar* ucp = in;
diff --git a/src/corelib/codecs/qtsciicodec.cpp b/src/corelib/codecs/qtsciicodec.cpp
index 7f660bf..c24d32d 100644
--- a/src/corelib/codecs/qtsciicodec.cpp
+++ b/src/corelib/codecs/qtsciicodec.cpp
@@ -82,8 +82,7 @@ QByteArray QTsciiCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
}
int invalid = 0;
- QByteArray rstr;
- rstr.resize(len);
+ QByteArray rstr(len, Qt::Uninitialized);
uchar* cursor = (uchar*)rstr.data();
for (int i = 0; i < len; i++) {
QChar ch = uc[i];
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index fe826ad..abae6f7 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -471,8 +471,7 @@ QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt
endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BE : LE;
}
- QByteArray d;
- d.resize(length);
+ QByteArray d(length, Qt::Uninitialized);
char *data = d.data();
if (!state || !(state->flags & IgnoreHeader)) {
if (endian == BE) {
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 398cd48..2023327 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1543,7 +1543,7 @@ public:
TitleBarArea // For move
};
- enum Uninitialized {
+ enum Initialization {
Uninitialized
};
}
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index c42c9c9..fd7ddef 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -333,10 +333,13 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal,
return 0;
}
int offset = (*signal == '0'+QSIGNAL_CODE) ? 1 : 0;
- if (sender->metaObject()->indexOfSignal(signal+offset) == -1) {
- qWarning("QState::addTransition: no such signal %s::%s",
- sender->metaObject()->className(), signal+offset);
- return 0;
+ const QMetaObject *meta = sender->metaObject();
+ if (meta->indexOfSignal(signal+offset) == -1) {
+ if (meta->indexOfSignal(QMetaObject::normalizedSignature(signal+offset)) == -1) {
+ qWarning("QState::addTransition: no such signal %s::%s",
+ meta->className(), signal+offset);
+ return 0;
+ }
}
QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target);
addTransition(trans);
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 758bdbe..682dd97 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1316,11 +1316,15 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
if (signal.startsWith('0'+QSIGNAL_CODE))
signal.remove(0, 1);
- int signalIndex = sender->metaObject()->indexOfSignal(signal);
+ const QMetaObject *meta = sender->metaObject();
+ int signalIndex = meta->indexOfSignal(signal);
if (signalIndex == -1) {
- qWarning("QSignalTransition: no such signal: %s::%s",
- sender->metaObject()->className(), signal.constData());
- return;
+ signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal));
+ if (signalIndex == -1) {
+ qWarning("QSignalTransition: no such signal: %s::%s",
+ meta->className(), signal.constData());
+ return;
+ }
}
QVector<int> &connectedSignalIndexes = connections[sender];
if (connectedSignalIndexes.size() <= signalIndex)
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 0c45776..5d3386e 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -1304,6 +1304,21 @@ QByteArray::QByteArray(int size, char ch)
}
/*!
+ \internal
+
+ Constructs a byte array of size \a size with uninitialized contents.
+*/
+
+QByteArray::QByteArray(int size, Qt::Initialization)
+{
+ d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
+/*!
Sets the size of the byte array to \a size bytes.
If \a size is greater than the current size, the byte array is
@@ -2977,8 +2992,7 @@ QByteArray QByteArray::simplified() const
{
if (d->size == 0)
return *this;
- QByteArray result;
- result.resize(d->size);
+ QByteArray result(d->size, Qt::Uninitialized);
const char *from = d->data;
const char *fromend = from + d->size;
int outc=0;
@@ -3429,8 +3443,7 @@ QByteArray QByteArray::toBase64() const
const char padchar = '=';
int padlen = 0;
- QByteArray tmp;
- tmp.resize(((d->size * 4) / 3) + 3);
+ QByteArray tmp((d->size * 4) / 3 + 3, Qt::Uninitialized);
int i = 0;
char *out = tmp.data();
@@ -3768,8 +3781,7 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64)
{
unsigned int buf = 0;
int nbits = 0;
- QByteArray tmp;
- tmp.resize((base64.size() * 3) / 4);
+ QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized);
int offset = 0;
for (int i = 0; i < base64.size(); ++i) {
@@ -3817,8 +3829,7 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64)
*/
QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
{
- QByteArray res;
- res.resize((hexEncoded.size() + 1)/ 2);
+ QByteArray res((hexEncoded.size() + 1)/ 2, Qt::Uninitialized);
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
@@ -3855,8 +3866,7 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
*/
QByteArray QByteArray::toHex() const
{
- QByteArray hex;
- hex.resize(d->size*2);
+ QByteArray hex(d->size * 2, Qt::Uninitialized);
char *hexData = hex.data();
const uchar *data = (const uchar *)d->data;
for (int i = 0; i < d->size; ++i) {
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 5cd4d63..e494ac1 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -42,8 +42,8 @@
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
-#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qnamespace.h>
#include <string.h>
#include <stdarg.h>
@@ -127,6 +127,7 @@ public:
QByteArray(const char *);
QByteArray(const char *, int size);
QByteArray(int size, char c);
+ QByteArray(int size, Qt::Initialization);
inline QByteArray(const QByteArray &);
inline ~QByteArray();
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index dba3d2a..3ff263d 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1012,14 +1012,13 @@ QString::QString(int size, QChar ch)
}
}
-/*!
- Constructs a string of the given \a size without initializing the
- characters. This is only used in \c QStringBuilder::toString().
+/*! \fn QString::QString(int size, Qt::Initialization)
+ \internal
- \internal
+ Constructs a string of the given \a size without initializing the
+ characters. This is only used in \c QStringBuilder::toString().
*/
-
-QString::QString(int size, enum Qt::Uninitialized)
+QString::QString(int size, Qt::Initialization)
{
d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
d->ref = 1;
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 67716b8..6bb0d8e 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -579,7 +579,7 @@ public:
bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
bool isRightToLeft() const { if (!d->clean) updateProperties(); return d->righttoleft; }
- QString(int size, enum Qt::Uninitialized);
+ QString(int size, Qt::Initialization);
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index b2c04ca..a304027 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -797,7 +797,7 @@ QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
{
// COMBINE
- if (itemIsUntransformable() && viewTransform) {
+ if (viewTransform && itemIsUntransformable()) {
*x = q_ptr->deviceTransform(*viewTransform);
} else {
if (transformData)
@@ -819,7 +819,7 @@ void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransf
void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
{
// COMBINE
- if (itemIsUntransformable() && viewTransform) {
+ if (viewTransform && itemIsUntransformable()) {
*x = q_ptr->deviceTransform(*viewTransform);
} else {
x->translate(pos.x(), pos.y());
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 4d4c3b4..6c97886 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -1424,6 +1424,63 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item)
return 0;
}
+QList<QGraphicsItem *> QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QTransform *const viewTransform,
+ QRegion *exposedRegion)
+{
+ if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) {
+ if (needSortTopLevelItems) {
+ needSortTopLevelItems = false;
+ qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
+ }
+ return topLevelItems;
+ }
+
+ const QRectF exposedRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
+ QRectF sceneRect;
+ QTransform invertedViewTransform(Qt::Uninitialized);
+ if (!viewTransform) {
+ sceneRect = exposedRect;
+ } else {
+ invertedViewTransform = viewTransform->inverted();
+ sceneRect = invertedViewTransform.mapRect(exposedRect);
+ }
+ if (!largestUntransformableItem.isEmpty()) {
+ // ### Nuke this when we move the indexing code into a separate
+ // class. All the largestUntransformableItem code should then go
+ // away, and the estimate function should return untransformable
+ // items as well.
+ QRectF untr = largestUntransformableItem;
+ QRectF ltri = !viewTransform ? untr : invertedViewTransform.mapRect(untr);
+ ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
+ sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
+ }
+
+ QList<QGraphicsItem *> tmp = estimateItemsInRect(sceneRect);
+ for (int i = 0; i < tmp.size(); ++i)
+ tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1;
+
+ // Sort if the toplevel list is unsorted.
+ if (needSortTopLevelItems) {
+ needSortTopLevelItems = false;
+ qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
+ }
+
+ QList<QGraphicsItem *> tli;
+ for (int i = 0; i < topLevelItems.size(); ++i) {
+ // ### Investigate smarter ways. Looping through all top level
+ // items is not optimal. If the BSP tree is to have maximum
+ // effect, it should be possible to sort the subset of items
+ // quickly. We must use this approach for now, as it's the only
+ // current way to keep the stable sorting order (insertion order).
+ QGraphicsItem *item = topLevelItems.at(i);
+ if (item->d_ptr->itemDiscovered) {
+ item->d_ptr->itemDiscovered = 0;
+ tli << item;
+ }
+ }
+ return tli;
+}
+
void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect,
QList<QGraphicsItem *> *items,
const QTransform &parentTransform,
@@ -5045,165 +5102,118 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
- const QTransform &viewTransform,
+ const QTransform *const viewTransform,
QRegion *exposedRegion, QWidget *widget,
- QList<QGraphicsItem *> *topLevelItems,
qreal parentOpacity)
{
- // Calculate opacity.
- qreal opacity;
- bool invisibleButChildIgnoresParentOpacity = false;
- if (item) {
- if (!item->d_ptr->visible)
- return;
- opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
- invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity();
- if (!invisibleButChildIgnoresParentOpacity)
- return;
- }
- } else {
- opacity = parentOpacity;
- }
-
- // Item is invisible.
- bool hasContents = item && !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
- bool invisible = !hasContents || invisibleButChildIgnoresParentOpacity;
-
- // Calculate the full transform for this item.
- bool wasDirtyParentSceneTransform = false;
- bool dontDrawItem = true;
- QTransform transform(Qt::Uninitialized);
- if (item) {
- if (item->d_ptr->itemIsUntransformable()) {
- transform = item->deviceTransform(viewTransform);
- } else {
- if (item->d_ptr->dirtySceneTransform) {
- item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
- : QTransform();
- item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
- item->d_ptr->dirtySceneTransform = 0;
- wasDirtyParentSceneTransform = true;
- }
- transform = item->d_ptr->sceneTransform;
- transform *= viewTransform;
- }
-
- if (!invisible) {
- QRectF brect = item->boundingRect();
- // ### This does not take the clip into account.
- _q_adjustRect(&brect);
- QRect viewBoundingRect = transform.mapRect(brect).toRect();
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
- viewBoundingRect.adjust(-1, -1, 1, 1);
- if (exposedRegion)
- dontDrawItem = !exposedRegion->intersects(viewBoundingRect);
- else
- dontDrawItem = viewBoundingRect.isEmpty();
- }
- }
+ Q_ASSERT(item);
- // Find and sort children.
- QList<QGraphicsItem *> tmp;
- QList<QGraphicsItem *> *children = 0;
- if (item) {
- children = &item->d_ptr->children;
- } else if (topLevelItems) {
- children = topLevelItems;
- } else if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) {
- children = &this->topLevelItems;
- } else {
- QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1)));
- if (!largestUntransformableItem.isEmpty()) {
- // ### Nuke this when we move the indexing code into a separate
- // class. All the largestUntransformableItem code should then go
- // away, and the estimate function should return untransformable
- // items as well.
- QRectF untr = largestUntransformableItem;
- QRectF ltri = viewTransform.inverted().mapRect(untr);
- ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
- sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
- }
- tmp = estimateItemsInRect(sceneRect);
+ if (!item->d_ptr->visible)
+ return;
- QList<QGraphicsItem *> tli;
- for (int i = 0; i < tmp.size(); ++i)
- tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1;
+ const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+ if (!itemHasContents && !itemHasChildren)
+ return; // Item has neither contents nor children!(?)
- // Sort if the toplevel list is unsorted.
- if (needSortTopLevelItems) {
- needSortTopLevelItems = false;
- qStableSort(this->topLevelItems.begin(),
- this->topLevelItems.end(), qt_notclosestLeaf);
- }
+ const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
+ const bool itemIsFullyTransparent = (opacity < 0.0001);
+ if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
+ return;
- for (int i = 0; i < this->topLevelItems.size(); ++i) {
- // ### Investigate smarter ways. Looping through all top level
- // items is not optimal. If the BSP tree is to have maximum
- // effect, it should be possible to sort the subset of items
- // quickly. We must use this approach for now, as it's the only
- // current way to keep the stable sorting order (insertion order).
- QGraphicsItem *item = this->topLevelItems.at(i);
- if (item->d_ptr->itemDiscovered) {
- item->d_ptr->itemDiscovered = 0;
- tli << item;
+ QTransform transform(Qt::Uninitialized);
+ QTransform *transformPtr = 0;
+#define ENSURE_TRANSFORM_PTR \
+ if (!transformPtr) { \
+ Q_ASSERT(!itemIsUntransformable); \
+ if (viewTransform) { \
+ transform = item->d_ptr->sceneTransform; \
+ transform *= *viewTransform; \
+ transformPtr = &transform; \
+ } else { \
+ transformPtr = &item->d_ptr->sceneTransform; \
+ } \
+ }
+
+ // Update the item's scene transform if the item is transformable;
+ // otherwise calculate the full transform,
+ bool wasDirtyParentSceneTransform = false;
+ const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
+ if (itemIsUntransformable) {
+ transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
+ transformPtr = &transform;
+ } else if (item->d_ptr->dirtySceneTransform) {
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ bool drawItem = itemHasContents && !itemIsFullyTransparent;
+ if (drawItem) {
+ const QRectF brect = adjustedItemBoundingRect(item);
+ ENSURE_TRANSFORM_PTR
+ QRect viewBoundingRect = transformPtr->mapRect(brect).toRect();
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ viewBoundingRect.adjust(-1, -1, 1, 1);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
+ if (!drawItem) {
+ if (!itemHasChildren)
+ return;
+ if (itemClipsChildrenToShape) {
+ if (wasDirtyParentSceneTransform)
+ item->d_ptr->invalidateChildrenSceneTransform();
+ return;
}
}
+ } // else we know for sure this item has children we must process.
- tmp = tli;
- children = &tmp;
- }
-
- bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
- bool dontDrawChildren = item && hasContents && dontDrawItem && childClip;
- childClip &= !dontDrawChildren && !children->isEmpty();
- if (item && invisible)
- dontDrawItem = true;
-
- // Clip children.
- if (childClip) {
- painter->save();
- painter->setWorldTransform(transform);
- painter->setClipPath(item->shape(), Qt::IntersectClip);
- }
-
- if (!dontDrawChildren) {
- if (item && item->d_ptr->needSortChildren) {
+ int i = 0;
+ if (itemHasChildren) {
+ if (item->d_ptr->needSortChildren) {
item->d_ptr->needSortChildren = 0;
- qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
- } else if (!item && needSortTopLevelItems && children != &tmp) {
- needSortTopLevelItems = false;
- qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
+ qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf);
}
- }
- // Draw children behind
- int i = 0;
- if (!dontDrawChildren) {
- // ### Don't visit children that don't ignore parent opacity if this
- // item is invisible.
- for (i = 0; i < children->size(); ++i) {
- QGraphicsItem *child = children->at(i);
+ if (itemClipsChildrenToShape) {
+ painter->save();
+ ENSURE_TRANSFORM_PTR
+ painter->setWorldTransform(*transformPtr);
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ }
+
+ // Draw children behind
+ for (i = 0; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
if (wasDirtyParentSceneTransform)
child->d_ptr->dirtySceneTransform = 1;
if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
break;
- drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget,
- 0, opacity);
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity);
}
}
// Draw item
- if (!dontDrawItem) {
- item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0);
-
- bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape);
- bool savePainter = clipsToShape || painterStateProtection;
+ if (drawItem) {
+ Q_ASSERT(!itemIsFullyTransparent);
+ Q_ASSERT(itemHasContents);
+ item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion
+ ? *exposedRegion : QRegion(), exposedRegion == 0);
+
+ const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
+ const bool savePainter = itemClipsToShape || painterStateProtection;
if (savePainter)
painter->save();
- if (!childClip)
- painter->setWorldTransform(transform);
- if (clipsToShape)
+
+ if (!itemHasChildren || !itemClipsChildrenToShape) {
+ ENSURE_TRANSFORM_PTR
+ painter->setWorldTransform(*transformPtr);
+ }
+ if (itemClipsToShape)
painter->setClipPath(item->shape(), Qt::IntersectClip);
painter->setOpacity(opacity);
@@ -5217,22 +5227,19 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
}
// Draw children in front
- if (!dontDrawChildren) {
- // ### Don't visit children that don't ignore parent opacity if this
- // item is invisible.
- for (; i < children->size(); ++i) {
- QGraphicsItem *child = children->at(i);
+ if (itemHasChildren) {
+ for (; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
if (wasDirtyParentSceneTransform)
child->d_ptr->dirtySceneTransform = 1;
- drawSubtreeRecursive(child, painter, viewTransform, exposedRegion,
- widget, 0, opacity);
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity);
}
- } else if (wasDirtyParentSceneTransform) {
- item->d_ptr->invalidateChildrenSceneTransform();
}
// Restore child clip
- if (childClip)
+ if (itemHasChildren && itemClipsChildrenToShape)
painter->restore();
}
@@ -5525,7 +5532,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
if (!item->d_ptr->itemDiscovered) {
topLevelItems << item;
item->d_ptr->itemDiscovered = 1;
- d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget);
+ d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
}
}
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index a8f6699..2f63e5b 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -206,6 +206,7 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
+ QList<QGraphicsItem *> topLevelItemsInStackingOrder(const QTransform *const, QRegion *);
void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList<QGraphicsItem *> *items,
const QTransform &parentTransform, const QTransform &viewTransform,
Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
@@ -259,10 +260,18 @@ public:
void drawItemHelper(QGraphicsItem *item, QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
-
- void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform,
- QRegion *exposedRegion, QWidget *widget,
- QList<QGraphicsItem *> *topLevelItems = 0, qreal parentOpacity = qreal(1.0));
+
+ inline void drawItems(QPainter *painter, const QTransform *const viewTransform,
+ QRegion *exposedRegion, QWidget *widget)
+ {
+ const QList<QGraphicsItem *> tli = topLevelItemsInStackingOrder(viewTransform, exposedRegion);
+ for (int i = 0; i < tli.size(); ++i)
+ drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget);
+ return;
+ }
+
+ void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
+ QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0));
void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
bool removingItemFromScene = false);
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 553d71c..1ba87ec 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -3298,8 +3298,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Items
if (!(d->optimizationFlags & IndirectPainting)) {
- d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion,
- viewport(), 0);
+ d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
+ &d->exposedRegion, viewport());
} else {
// Find all exposed items
bool allItems = false;
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 942836a..babc5df 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -1085,10 +1085,8 @@ static void qt_set_input_encoding()
}
// Reads a KDE color setting
-static QColor kdeColor(const QString &key)
+static QColor kdeColor(const QString &key, const QSettings &kdeSettings)
{
- QSettings kdeSettings(QApplicationPrivate::kdeHome() +
- QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
QVariant variant = kdeSettings.value(key);
if (variant.isValid()) {
QStringList values = variant.toStringList();
@@ -1307,36 +1305,40 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
}
if (kdeColors) {
+ const QSettings &theKdeSettings =
+ QSettings(QApplicationPrivate::kdeHome()
+ + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+
// Setup KDE palette
QColor color;
- color = kdeColor(QLatin1String("buttonBackground"));
+ color = kdeColor(QLatin1String("buttonBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"), theKdeSettings);
if (color.isValid())
btn = color;
- color = kdeColor(QLatin1String("background"));
+ color = kdeColor(QLatin1String("background"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"), theKdeSettings);
if (color.isValid())
bg = color;
- color = kdeColor(QLatin1String("foreground"));
+ color = kdeColor(QLatin1String("foreground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"), theKdeSettings);
if (color.isValid()) {
fg = color;
}
- color = kdeColor(QLatin1String("windowForeground"));
+ color = kdeColor(QLatin1String("windowForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"), theKdeSettings);
if (color.isValid())
wfg = color;
- color = kdeColor(QLatin1String("windowBackground"));
+ color = kdeColor(QLatin1String("windowBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"), theKdeSettings);
if (color.isValid())
base = color;
}
@@ -1355,29 +1357,33 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
}
// Use KDE3 or KDE4 color settings if present
if (kdeColors) {
- QColor color = kdeColor(QLatin1String("selectBackground"));
+ const QSettings &theKdeSettings =
+ QSettings(QApplicationPrivate::kdeHome()
+ + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+
+ QColor color = kdeColor(QLatin1String("selectBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"), theKdeSettings);
if (color.isValid())
highlight = color;
- color = kdeColor(QLatin1String("selectForeground"));
+ color = kdeColor(QLatin1String("selectForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"), theKdeSettings);
if (color.isValid())
highlightText = color;
- color = kdeColor(QLatin1String("alternateBackground"));
+ color = kdeColor(QLatin1String("alternateBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"));
+ color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"), theKdeSettings);
if (color.isValid())
pal.setColor(QPalette::AlternateBase, color);
else
pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
- color = kdeColor(QLatin1String("buttonForeground"));
+ color = kdeColor(QLatin1String("buttonForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"), theKdeSettings);
if (color.isValid())
pal.setColor(QPalette::ButtonText, color);
}
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index 62addd3..221267f 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -198,7 +198,7 @@ QT_BEGIN_NAMESPACE
QMatrix member functions
*****************************************************************************/
/*!
- \fn QMatrix::QMatrix(Qt::Uninitialized)
+ \fn QMatrix::QMatrix(Qt::Initialization)
\internal
*/
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index b2e5d70..aa4177c 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -61,7 +61,7 @@ class QVariant;
class Q_GUI_EXPORT QMatrix // 2D transform matrix
{
public:
- inline explicit QMatrix(enum Qt::Uninitialized) {}
+ inline explicit QMatrix(Qt::Initialization) {}
QMatrix();
QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
qreal dx, qreal dy);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 78515ac..37f7b6d 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1771,10 +1771,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- int x1 = int(rect.x() + aliasedCoordinateDelta);
- int y1 = int(rect.y() + aliasedCoordinateDelta);
- int x2 = int(rect.right() + aliasedCoordinateDelta);
- int y2 = int(rect.bottom() + aliasedCoordinateDelta);
+ int x1 = qRound(rect.x() + aliasedCoordinateDelta);
+ int y1 = qRound(rect.y() + aliasedCoordinateDelta);
+ int x2 = qRound(rect.right() + aliasedCoordinateDelta);
+ int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
if (x2 < x1)
qSwap(x1, x2);
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index f94c353..30c22b2 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -179,7 +179,7 @@ private:
};
-class QStroker : public QStrokerOps
+class Q_GUI_EXPORT QStroker : public QStrokerOps
{
public:
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 85adb27..f0b2351 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -232,7 +232,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QTransform::QTransform(Qt::Uninitialized)
+ \fn QTransform::QTransform(Qt::Initialization)
\internal
*/
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index f99b0e7..291d35c 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -71,7 +71,7 @@ public:
TxProject = 0x10
};
- inline explicit QTransform(enum Qt::Uninitialized) : affine(Qt::Uninitialized) {}
+ inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {}
QTransform();
QTransform(qreal h11, qreal h12, qreal h13,
qreal h21, qreal h22, qreal h23,
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 135bcda..3125304 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -155,6 +155,11 @@ QSize QDockAreaLayoutItem::maximumSize() const
return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
+bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o) const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
{
if ((flags & GapItem) || placeHolderItem != 0)
@@ -216,7 +221,7 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
#endif
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), rect(0, 0, -1, -1), mainWindow(0)
+ : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth)
#endif
@@ -226,7 +231,7 @@ QDockAreaLayoutInfo::QDockAreaLayoutInfo()
QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
- : sep(_sep), dockPos(_dockPos), o(_o), rect(0, 0, -1, -1), mainWindow(window)
+ : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
#endif
@@ -244,7 +249,7 @@ QSize QDockAreaLayoutInfo::size() const
void QDockAreaLayoutInfo::clear()
{
item_list.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
#ifndef QT_NO_TABBAR
tabbed = false;
tabBar = 0;
@@ -388,10 +393,9 @@ QSize QDockAreaLayoutInfo::sizeHint() const
return QSize(0, 0);
int a = 0, b = 0;
- bool prev_gap = false;
- bool first = true;
int min_perp = 0;
int max_perp = QWIDGETSIZE_MAX;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -409,14 +413,15 @@ QSize QDockAreaLayoutInfo::sizeHint() const
} else
#endif
{
- if (!first && !gap && !prev_gap)
+ if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
+ && !previous->hasFixedSize(o)) {
a += sep;
+ }
a += gap ? item.size : pick(o, size_hint);
}
b = qMax(b, perp(o, size_hint));
- prev_gap = gap;
- first = false;
+ previous = &item;
}
max_perp = qMax(max_perp, min_perp);
@@ -539,21 +544,20 @@ void QDockAreaLayoutInfo::fitItems()
int max_size = realMaxSize(*this);
int last_index = -1;
- bool prev_gap = false;
- bool first = true;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
continue;
bool gap = item.flags & QDockAreaLayoutItem::GapItem;
- if (!first && !gap && !prev_gap) {
- QLayoutStruct &ls = layout_struct_list[j++];
- ls.init();
- ls.minimumSize = sep;
- ls.maximumSize = sep;
- ls.sizeHint = sep;
- ls.empty = false;
+ if (previous && !gap) {
+ if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
+ QLayoutStruct &ls = layout_struct_list[j++];
+ ls.init();
+ ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+ ls.empty = false;
+ }
}
if (item.flags & QDockAreaLayoutItem::KeepSize) {
@@ -592,8 +596,7 @@ void QDockAreaLayoutInfo::fitItems()
}
item.flags &= ~QDockAreaLayoutItem::KeepSize;
- prev_gap = gap;
- first = false;
+ previous = &item;
}
layout_struct_list.resize(j);
@@ -607,8 +610,8 @@ void QDockAreaLayoutInfo::fitItems()
qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
j = 0;
- prev_gap = false;
- first = true;
+ bool prev_gap = false;
+ bool first = true;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
@@ -1408,11 +1411,12 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
continue;
- int margin = (sep == 1? 2 : 0);
- if (pos >= item.pos + item.size - margin && item.pos + item.size + sep + margin > pos) {
- QList<int> result;
- result.append(i);
- return result;
+ QRect sepRect = separatorRect(i);
+ if (!sepRect.isNull() && sep == 1)
+ sepRect.adjust(-2, -2, 2, 2);
+ //we also make sure we don't find a separator that's not there
+ if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
+ return QList<int>() << i;
}
}
@@ -1478,6 +1482,12 @@ QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
return result;
}
+bool QDockAreaLayoutInfo::hasFixedSize() const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
+
void QDockAreaLayoutInfo::apply(bool animate)
{
QWidgetAnimator *widgetAnimator = mainWindowLayout()->widgetAnimator;
@@ -1629,7 +1639,7 @@ void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
if (next == -1)
break;
QRect r = separatorRect(i);
- if (clip.contains(r))
+ if (clip.contains(r) && !item.hasFixedSize(o))
paintSep(p, widget, r, o, r.contains(mouse));
}
}
@@ -2009,10 +2019,8 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
void QDockAreaLayoutInfo::updateSeparatorWidgets() const
{
- QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
-
if (tabbed) {
- that->separatorWidgets.clear();
+ separatorWidgets.clear();
return;
}
@@ -2040,7 +2048,7 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = mainWindowLayout()->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -2053,10 +2061,10 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget->show();
}
- for (int k = j; k < that->separatorWidgets.size(); ++k) {
- that->separatorWidgets[k]->hide();
+ for (int k = j; k < separatorWidgets.size(); ++k) {
+ separatorWidgets[k]->hide();
}
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
Q_ASSERT(separatorWidgets.size() == j);
}
@@ -2271,7 +2279,7 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win)
docks[QInternal::BottomDock]
= QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
- centralWidgetRect = QRect(0, 0, -1, -1);
+
corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
@@ -2442,9 +2450,9 @@ QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
if (info.isEmpty())
continue;
QRect rect = separatorRect(i);
- if (sep == 1)
+ if (!rect.isNull() && sep == 1)
rect.adjust(-2, -2, 2, 2);
- if (rect.contains(pos)) {
+ if (rect.contains(pos) && !info.hasFixedSize()) {
result << i;
break;
} else if (info.rect.contains(pos)) {
@@ -2504,9 +2512,10 @@ QRect QDockAreaLayout::itemRect(QList<int> path) const
QRect QDockAreaLayout::separatorRect(int index) const
{
- if (docks[index].isEmpty())
+ const QDockAreaLayoutInfo &dock = docks[index];
+ if (dock.isEmpty())
return QRect();
- QRect r = docks[index].rect;
+ QRect r = dock.rect;
switch (index) {
case QInternal::LeftDock:
return QRect(r.right() + 1, r.top(), sep, r.height());
@@ -2854,8 +2863,8 @@ void QDockAreaLayout::clear()
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
- centralWidgetRect = QRect(0, 0, -1, -1);
+ rect = QRect();
+ centralWidgetRect = QRect();
}
QSize QDockAreaLayout::sizeHint() const
@@ -3080,7 +3089,7 @@ void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
if (dock.isEmpty())
continue;
QRect r = separatorRect(i);
- if (clip.contains(r)) {
+ if (clip.contains(r) && !dock.hasFixedSize()) {
Qt::Orientation opposite = dock.o == Qt::Horizontal
? Qt::Vertical : Qt::Horizontal;
paintSep(p, widget, r, opposite, r.contains(mouse));
@@ -3154,8 +3163,6 @@ int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin,
// Allocates new sepearator widgets with getSeparatorWidget
void QDockAreaLayout::updateSeparatorWidgets() const
{
- QDockAreaLayout *that = const_cast<QDockAreaLayout*>(this);
-
int j = 0;
for (int i = 0; i < QInternal::DockCount; ++i) {
@@ -3168,7 +3175,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -3183,7 +3190,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
for (int i = j; i < separatorWidgets.size(); ++i)
separatorWidgets.at(i)->hide();
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
}
QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0b8d832..137aeba 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -103,6 +103,7 @@ struct QDockAreaLayoutItem
QSize maximumSize() const;
QSize sizeHint() const;
bool expansive(Qt::Orientation o) const;
+ bool hasFixedSize(Qt::Orientation o) const;
QLayoutItem *widgetItem;
QDockAreaLayoutInfo *subinfo;
@@ -167,6 +168,7 @@ public:
void clear();
bool isEmpty() const;
+ bool hasFixedSize() const;
QList<int> findSeparator(const QPoint &pos) const;
int next(int idx) const;
int prev(int idx) const;
@@ -188,7 +190,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
int sep;
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
QRect rect;
@@ -231,7 +233,7 @@ public:
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
int sep; // separator extent
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
bool isValid() const;
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index 308f956..10e07d3 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -490,10 +490,10 @@ void QMainWindowLayoutState::clear()
#ifndef QT_NO_DOCKWIDGET
dockAreaLayout.clear();
#else
- centralWidgetRect = QRect(0, 0, -1, -1);
+ centralWidgetRect = QRect();
#endif
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
bool QMainWindowLayoutState::isValid() const
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 6bbf4e8..fc55a2c 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -1826,7 +1826,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone
&& !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, 0, this)) {
int below_height = above_height + d->scroll->scrollOffset;
- for(int i2 = i; i2 < (int)d->actionList.count(); i2++)
+ for(int i2 = i; i2 < d->actionList.count(); i2++)
below_height += d->actionRects.value(d->actionList.at(i2)).height();
size.setHeight(below_height);
}
@@ -2263,7 +2263,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
break;
}
}
- if (e->button() == Qt::LeftButton || (e->button() == Qt::RightButton && isContextMenu))
+ if (e->button() || isContextMenu)
#endif
d->activateAction(action, QAction::Trigger);
}
@@ -2746,7 +2746,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
if (d->hasHadMouse && !rect().contains(e->pos()))
d->setCurrentAction(0);
return;
- } else if(e->buttons() & (Qt::LeftButton | Qt::RightButton)) {
+ } else if(e->buttons()) {
d->mouseDown = this;
}
if (d->sloppyRegion.contains(e->pos())) {
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index efacd00..4977b31 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -1029,15 +1029,14 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
\section1 Using QPlainTextEdit as a Display Widget
- The text is set or replaced using setPlainText() which deletes any
- existing text and replaces it with the text passed in the
- setPlainText() call.
+ The text is set or replaced using setPlainText() which deletes the
+ existing text and replaces it with the text passed to setPlainText().
- Text itself can be inserted using the QTextCursor class or using
- the convenience functins insertPlainText(), appendPlainText() or
+ Text can be inserted using the QTextCursor class or using the
+ convenience functions insertPlainText(), appendPlainText() or
paste().
- By default the text edit wraps words at whitespace to fit within
+ By default, the text edit wraps words at whitespace to fit within
the text edit widget. The setLineWrapMode() function is used to
specify the kind of line wrap you want, \l WidgetWidth or \l
NoWrap if you don't want any wrapping. If you use word wrap to
diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp
index aaab885..8a10355 100644
--- a/src/gui/widgets/qtoolbararealayout.cpp
+++ b/src/gui/widgets/qtoolbararealayout.cpp
@@ -567,7 +567,7 @@ bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
void QToolBarAreaLayoutInfo::clear()
{
lines.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
QRect QToolBarAreaLayoutInfo::itemRect(QList<int> path) const
@@ -1101,7 +1101,7 @@ void QToolBarAreaLayout::clear()
{
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
QToolBarAreaLayoutItem &QToolBarAreaLayout::item(QList<int> path)
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index ed2f220..907aaef 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -112,8 +112,6 @@ static void ensureInitialized()
are supplied that take a request and optional data, and each return a
QNetworkReply object. The returned object is used to obtain any data
returned in response to the corresponding request.
- the reply to is where most of the signals as well
- as the downloaded data are posted.
A simple download off the network could be accomplished with:
\snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 0
@@ -122,7 +120,8 @@ static void ensureInitialized()
takes is the QNetworkReply object containing the downloaded data
as well as meta-data (headers, etc.).
- \note The slot is responsible for deleting the object at that point.
+ \note After the request has finished, it is the responsibility of the user
+ to delete the QNetworkReply object at an appropriate time.
A more involved example, assuming the manager is already existent,
can be:
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 5df6b0f..50aaa6a 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -81,6 +81,20 @@ QT_BEGIN_NAMESPACE
use on the system to 50MB.
Note you have to set the cache directory before it will work.
+
+ A network disk cache can be enabled by:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 0
+
+ When sending requests, to control the preference of when to use the cache
+ and when to use the network, consider the following:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 1
+
+ To check whether the response came from the cache or from the network, the
+ following can be applied:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 2
*/
/*!
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 1c86466..9dc7818 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -237,6 +237,7 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
w = rect.width();
h = rect.height();
d = otherData->d;
+ is_null = (w <= 0 || h <= 0);
DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
#if (Q_DIRECTFB_VERSION >= 0x010000)
dfbSurface->ReleaseSource(dfbSurface);
@@ -330,6 +331,8 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect);
data->w = size.width();
data->h = size.height();
+ data->is_null = (data->w <= 0 || data->h <= 0);
+
#if (Q_DIRECTFB_VERSION >= 0x010000)
data->dfbSurface->ReleaseSource(data->dfbSurface);
#endif
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
index ad6c38e..e81aef4 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
@@ -60,22 +60,23 @@ public:
~QDirectFBPixmapData();
// Re-implemented from QPixmapData:
- void resize(int width, int height);
- void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
- void copy(const QPixmapData *data, const QRect &rect);
- void fill(const QColor &color);
- inline bool hasAlphaChannel() const { return alpha; }
- QPixmap transformed(const QTransform &matrix,
- Qt::TransformationMode mode) const;
- QImage toImage() const;
- QPaintEngine* paintEngine() const;
+ virtual void resize(int width, int height);
+ virtual void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ virtual void copy(const QPixmapData *data, const QRect &rect);
+ virtual void fill(const QColor &color);
+ virtual QPixmap transformed(const QTransform &matrix,
+ Qt::TransformationMode mode) const;
+ virtual QImage toImage() const;
+ virtual QPaintEngine *paintEngine() const;
virtual QImage *buffer();
+ virtual int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);}
+
QImage *buffer(uint lockFlags);
// Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice
- int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);}
inline QImage::Format pixelFormat() const { return format; }
static bool hasAlphaChannel(const QImage &img);
+ inline bool hasAlphaChannel() const { return alpha; }
private:
void invalidate();
QDirectFBPaintEngine *engine;
diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp
index b6ca82d..1a82377 100644
--- a/src/sql/drivers/db2/qsql_db2.cpp
+++ b/src/sql/drivers/db2/qsql_db2.cpp
@@ -1043,26 +1043,22 @@ QVariant QDB2Result::data(int field)
case QVariant::Double:
{
QString value=qGetStringData(d->hStmt, field, info.length() + 1, isNull);
- bool ok=false;
- switch(d->precisionPolicy) {
+ switch(numericalPrecisionPolicy()) {
case QSql::LowPrecisionInt32:
- v = new QVariant(value.toInt(&ok));
+ v = new QVariant(qGetIntData(d->hStmt, field, isNull));
break;
case QSql::LowPrecisionInt64:
- v = new QVariant(value.toLongLong(&ok));
+ v = new QVariant(qGetBigIntData(d->hStmt, field, isNull));
break;
case QSql::LowPrecisionDouble:
- v = new QVariant(value.toDouble(&ok));
+ v = new QVariant(qGetDoubleData(d->hStmt, field, isNull));
break;
case QSql::HighPrecision:
default:
// length + 1 for the comma
- v = new QVariant(value);
- ok = true;
+ v = new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull));
break;
}
- if(!ok)
- v = new QVariant();
break;
}
case QVariant::String:
@@ -1146,6 +1142,10 @@ void QDB2Result::virtual_hook(int id, void *data)
Q_ASSERT(data);
*static_cast<bool*>(data) = nextResult();
break;
+ case QSqlResult::DetachFromResultSet:
+ if (d->hStmt)
+ SQLCloseCursor(d->hStmt);
+ break;
default:
QSqlResult::virtual_hook(id, data);
}
@@ -1177,7 +1177,7 @@ QDB2Driver::~QDB2Driver()
delete d;
}
-bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString&, int,
+bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString& host, int port,
const QString& connOpts)
{
if (isOpen())
@@ -1200,6 +1200,8 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas
setOpenError(true);
return false;
}
+
+ QString protocol;
// Set connection attributes
const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
for (int i = 0; i < opts.count(); ++i) {
@@ -1230,7 +1232,10 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas
} else if (opt == QLatin1String("SQL_ATTR_LOGIN_TIMEOUT")) {
v = val.toUInt();
r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) v, 0);
- } else {
+ } else if (opt.compare(QLatin1String("PROTOCOL"), Qt::CaseInsensitive) == 0) {
+ protocol = tmp;
+ }
+ else {
qWarning("QDB2Driver::open: Unknown connection attribute '%s'",
tmp.toLocal8Bit().constData());
}
@@ -1239,9 +1244,18 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas
"Unable to set connection attribute '%1'").arg(opt), d);
}
+ if (protocol.isEmpty())
+ protocol = QLatin1String("PROTOCOL=TCPIP");
+
+ if (port < 0 )
+ port = 50000;
+
QString connQStr;
- connQStr = QLatin1String("DSN=") + db + QLatin1String(";UID=") + user + QLatin1String(";PWD=")
- + password;
+ connQStr = protocol + QLatin1String(";DATABASE=") + db + QLatin1String(";HOSTNAME=") + host
+ + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user
+ + QLatin1String(";PWD=") + password;
+
+
SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH];
SQLSMALLINT cb;
@@ -1260,7 +1274,7 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas
return false;
}
- d->user = user.toUpper();
+ d->user = user;
setOpen(true);
setOpenError(false);
return true;
@@ -1305,10 +1319,25 @@ QSqlRecord QDB2Driver::record(const QString& tableName) const
SQLHANDLE hStmt;
QString catalog, schema, table;
- qSplitTableQualifier(tableName.toUpper(), &catalog, &schema, &table);
+ qSplitTableQualifier(tableName, &catalog, &schema, &table);
if (schema.isEmpty())
schema = d->user;
+ if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
+ catalog = stripDelimiters(catalog, QSqlDriver::TableName);
+ else
+ catalog = catalog.toUpper();
+
+ if (isIdentifierEscaped(schema, QSqlDriver::TableName))
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ else
+ schema = schema.toUpper();
+
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+ else
+ table = table.toUpper();
+
SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
d->hDbc,
&hStmt);
@@ -1322,6 +1351,9 @@ QSqlRecord QDB2Driver::record(const QString& tableName) const
(SQLPOINTER) SQL_CURSOR_FORWARD_ONLY,
SQL_IS_UINTEGER);
+
+ //Aside: szSchemaName and szTableName parameters of SQLColumns
+ //are case sensitive search patterns, so no escaping is used.
r = SQLColumns(hStmt,
NULL,
0,
@@ -1402,7 +1434,13 @@ QStringList QDB2Driver::tables(QSql::TableType type) const
bool isNull;
QString fieldVal = qGetStringData(hStmt, 2, -1, isNull);
QString userVal = qGetStringData(hStmt, 1, -1, isNull);
- if (userVal != d->user)
+ QString user = d->user;
+ if ( isIdentifierEscaped(user, QSqlDriver::TableName))
+ user = stripDelimiters(user, QSqlDriver::TableName);
+ else
+ user = user.toUpper();
+
+ if (userVal != user)
fieldVal = userVal + QLatin1Char('.') + fieldVal;
tl.append(fieldVal);
r = SQLFetchScroll(hStmt,
@@ -1433,7 +1471,23 @@ QSqlIndex QDB2Driver::primaryIndex(const QString& tablename) const
return index;
}
QString catalog, schema, table;
- qSplitTableQualifier(tablename.toUpper(), &catalog, &schema, &table);
+ qSplitTableQualifier(tablename, &catalog, &schema, &table);
+
+ if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
+ catalog = stripDelimiters(catalog, QSqlDriver::TableName);
+ else
+ catalog = catalog.toUpper();
+
+ if (isIdentifierEscaped(schema, QSqlDriver::TableName))
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ else
+ schema = schema.toUpper();
+
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+ else
+ table = table.toUpper();
+
r = SQLSetStmtAttr(hStmt,
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
@@ -1477,7 +1531,6 @@ bool QDB2Driver::hasFeature(DriverFeature f) const
case BatchOperations:
case LastInsertId:
case SimpleLocking:
- case LowPrecisionNumbers:
case EventNotifications:
return false;
case BLOB:
@@ -1485,6 +1538,8 @@ bool QDB2Driver::hasFeature(DriverFeature f) const
case MultipleResultSets:
case PreparedQueries:
case PositionalPlaceholders:
+ case LowPrecisionNumbers:
+ case FinishQuery:
return true;
case Unicode:
// this is the query that shows the codepage for the types:
diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp
index 0698f26..d714327 100644
--- a/src/sql/drivers/ibase/qsql_ibase.cpp
+++ b/src/sql/drivers/ibase/qsql_ibase.cpp
@@ -1103,6 +1103,19 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx)
// null value
QVariant v;
v.convert(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype, d->sqlda->sqlvar[i].sqlscale < 0));
+ if(v.type() == QVariant::Double) {
+ switch(numericalPrecisionPolicy()) {
+ case QSql::LowPrecisionInt32:
+ v.convert(QVariant::Int);
+ break;
+ case QSql::LowPrecisionInt64:
+ v.convert(QVariant::LongLong);
+ break;
+ case QSql::HighPrecision:
+ v.convert(QVariant::String);
+ break;
+ }
+ }
row[idx] = v;
continue;
}
@@ -1168,6 +1181,27 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx)
row[idx] = QVariant();
break;
}
+ if (d->sqlda->sqlvar[i].sqlscale < 0) {
+ QVariant v = row[idx];
+ switch(numericalPrecisionPolicy()) {
+ case QSql::LowPrecisionInt32:
+ if(v.convert(QVariant::Int))
+ row[idx]=v;
+ break;
+ case QSql::LowPrecisionInt64:
+ if(v.convert(QVariant::LongLong))
+ row[idx]=v;
+ break;
+ case QSql::LowPrecisionDouble:
+ if(v.convert(QVariant::Double))
+ row[idx]=v;
+ break;
+ case QSql::HighPrecision:
+ if(v.convert(QVariant::String))
+ row[idx]=v;
+ break;
+ }
+ }
}
return true;
@@ -1339,7 +1373,6 @@ bool QIBaseDriver::hasFeature(DriverFeature f) const
case LastInsertId:
case BatchOperations:
case SimpleLocking:
- case LowPrecisionNumbers:
case FinishQuery:
case MultipleResultSets:
return false;
@@ -1349,6 +1382,7 @@ bool QIBaseDriver::hasFeature(DriverFeature f) const
case Unicode:
case BLOB:
case EventNotifications:
+ case LowPrecisionNumbers:
return true;
}
return false;
@@ -1558,12 +1592,16 @@ QSqlRecord QIBaseDriver::record(const QString& tablename) const
QSqlQuery q(createResult());
q.setForwardOnly(true);
-
+ QString table = tablename;
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+ else
+ table = table.toUpper();
q.exec(QLatin1String("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE, b.RDB$FIELD_LENGTH, "
"b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG "
"FROM RDB$RELATION_FIELDS a, RDB$FIELDS b "
"WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE "
- "AND a.RDB$RELATION_NAME = '") + tablename.toUpper() + QLatin1String("' "
+ "AND a.RDB$RELATION_NAME = '") + table + QLatin1String("' "
"ORDER BY a.RDB$FIELD_POSITION"));
while (q.next()) {
@@ -1591,12 +1629,18 @@ QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const
if (!isOpen())
return index;
+ QString tablename = table;
+ if (isIdentifierEscaped(tablename, QSqlDriver::TableName))
+ tablename = stripDelimiters(tablename, QSqlDriver::TableName);
+ else
+ tablename = tablename.toUpper();
+
QSqlQuery q(createResult());
q.setForwardOnly(true);
q.exec(QLatin1String("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE, d.RDB$FIELD_SCALE "
"FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d "
"WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' "
- "AND a.RDB$RELATION_NAME = '") + table.toUpper() +
+ "AND a.RDB$RELATION_NAME = '") + tablename +
QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME "
"AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME "
"AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME "
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 46726a5..bfd65fc 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -254,6 +254,9 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
case FIELD_TYPE_FLOAT :
case FIELD_TYPE_DOUBLE :
case FIELD_TYPE_DECIMAL :
+#if defined(FIELD_TYPE_NEWDECIMAL)
+ case FIELD_TYPE_NEWDECIMAL:
+#endif
type = QVariant::Double;
break;
case FIELD_TYPE_DATE :
diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp
index ca4b286..d5fb10f 100644
--- a/src/sql/drivers/oci/qsql_oci.cpp
+++ b/src/sql/drivers/oci/qsql_oci.cpp
@@ -1899,7 +1899,7 @@ void QOCIResult::virtual_hook(int id, void *data)
QOCICols::execBatch(d, boundValues(), *reinterpret_cast<bool *>(data));
break;
default:
- QSqlResult::virtual_hook(id, data);
+ QSqlCachedResult::virtual_hook(id, data);
}
}
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index 727c5ce..b70868d 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -598,6 +598,7 @@ QChar QODBCDriverPrivate::quoteChar() const
return quote;
}
+
bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
{
// Set any connection attributes
diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp
index db09e93..1ab8214 100644
--- a/src/sql/drivers/psql/qsql_psql.cpp
+++ b/src/sql/drivers/psql/qsql_psql.cpp
@@ -891,6 +891,16 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
QString schema;
qSplitTableName(tbl, schema);
+ if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
+ tbl = stripDelimiters(tbl, QSqlDriver::TableName);
+ else
+ tbl = tbl.toLower();
+
+ if (isIdentifierEscaped(schema, QSqlDriver::TableName))
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ else
+ schema = schema.toLower();
+
switch(d->pro) {
case QPSQLDriver::Version6:
stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname "
@@ -923,7 +933,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
"FROM pg_attribute, pg_class "
"WHERE %1 pg_class.oid IN "
"(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
- " (SELECT oid FROM pg_class WHERE lower(relname) = '%2')) "
+ " (SELECT oid FROM pg_class WHERE relname = '%2')) "
"AND pg_attribute.attrelid = pg_class.oid "
"AND pg_attribute.attisdropped = false "
"ORDER BY pg_attribute.attnum");
@@ -931,11 +941,11 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND"));
else
stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema.toLower()));
+ "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema));
break;
}
- i.exec(stmt.arg(tbl.toLower()));
+ i.exec(stmt.arg(tbl));
while (i.isActive() && i.next()) {
QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt()));
idx.append(f);
@@ -954,6 +964,16 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
QString schema;
qSplitTableName(tbl, schema);
+ if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
+ tbl = stripDelimiters(tbl, QSqlDriver::TableName);
+ else
+ tbl = tbl.toLower();
+
+ if (isIdentifierEscaped(schema, QSqlDriver::TableName))
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ else
+ schema = schema.toLower();
+
QString stmt;
switch(d->pro) {
case QPSQLDriver::Version6:
@@ -998,7 +1018,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
"left join pg_attrdef on (pg_attrdef.adrelid = "
"pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
"where %1 "
- "and lower(pg_class.relname) = '%2' "
+ "and pg_class.relname = '%2' "
"and pg_attribute.attnum > 0 "
"and pg_attribute.attrelid = pg_class.oid "
"and pg_attribute.attisdropped = false "
@@ -1007,12 +1027,12 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)"));
else
stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1')").arg(schema.toLower()));
+ "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
break;
}
QSqlQuery query(createResult());
- query.exec(stmt.arg(tbl.toLower()));
+ query.exec(stmt.arg(tbl));
if (d->pro >= QPSQLDriver::Version71) {
while (query.next()) {
int len = query.value(3).toInt();
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index 1a05873..8e1091b 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -289,7 +289,7 @@ void QSQLiteResult::virtual_hook(int id, void *data)
sqlite3_reset(d->stmt);
break;
default:
- QSqlResult::virtual_hook(id, data);
+ QSqlCachedResult::virtual_hook(id, data);
}
}
@@ -656,9 +656,13 @@ QSqlIndex QSQLiteDriver::primaryIndex(const QString &tblname) const
if (!isOpen())
return QSqlIndex();
+ QString table = tblname;
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+
QSqlQuery q(createResult());
q.setForwardOnly(true);
- return qGetTableInfo(q, tblname, true);
+ return qGetTableInfo(q, table, true);
}
QSqlRecord QSQLiteDriver::record(const QString &tbl) const
@@ -666,9 +670,13 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const
if (!isOpen())
return QSqlRecord();
+ QString table = tbl;
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+
QSqlQuery q(createResult());
q.setForwardOnly(true);
- return qGetTableInfo(q, tbl);
+ return qGetTableInfo(q, table);
}
QVariant QSQLiteDriver::handle() const
@@ -676,10 +684,10 @@ QVariant QSQLiteDriver::handle() const
return qVariantFromValue(d->access);
}
-QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const
+QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !isIdentifierEscaped(identifier, type) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
index 790c1ef..1989c45 100644
--- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
@@ -260,7 +260,7 @@ void QSQLite2Result::virtual_hook(int id, void *data)
d->finalize();
break;
default:
- QSqlResult::virtual_hook(id, data);
+ QSqlCachedResult::virtual_hook(id, data);
}
}
diff --git a/src/sql/drivers/tds/qsql_tds.cpp b/src/sql/drivers/tds/qsql_tds.cpp
index 5ddc4e4..e100863 100644
--- a/src/sql/drivers/tds/qsql_tds.cpp
+++ b/src/sql/drivers/tds/qsql_tds.cpp
@@ -293,6 +293,8 @@ QTDSResult::QTDSResult(const QTDSDriver* db)
// insert d in error handler dict
errs()->insert(d->dbproc, d);
+ dbcmd(d->dbproc, "set quoted_identifier on");
+ dbsqlexec(d->dbproc);
}
QTDSResult::~QTDSResult()
@@ -367,7 +369,7 @@ bool QTDSResult::gotoNext(QSqlCachedResult::ValueCache &values, int index)
if (qIsNull(d->buffer.at(i * 2 + 1)))
values[idx] = QVariant(QVariant::String);
else
- values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2));
+ values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)).trimmed();
break;
case QVariant::ByteArray: {
if (qIsNull(d->buffer.at(i * 2 + 1)))
@@ -698,9 +700,14 @@ QSqlRecord QTDSDriver::record(const QString& tablename) const
return info;
QSqlQuery t(createResult());
t.setForwardOnly(true);
+
+ QString table = tablename;
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+
QString stmt (QLatin1String("select name, type, length, prec from syscolumns "
"where id = (select id from sysobjects where name = '%1')"));
- t.exec(stmt.arg(tablename));
+ t.exec(stmt.arg(table));
while (t.next()) {
QSqlField f(t.value(0).toString().simplified(), qDecodeTDSType(t.value(1).toInt()));
f.setLength(t.value(2).toInt());
@@ -770,13 +777,17 @@ QSqlIndex QTDSDriver::primaryIndex(const QString& tablename) const
{
QSqlRecord rec = record(tablename);
- QSqlIndex idx(tablename);
- if ((!isOpen()) || (tablename.isEmpty()))
+ QString table = tablename;
+ if (isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = stripDelimiters(table, QSqlDriver::TableName);
+
+ QSqlIndex idx(table);
+ if ((!isOpen()) || (table.isEmpty()))
return QSqlIndex();
QSqlQuery t(createResult());
t.setForwardOnly(true);
- t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(tablename));
+ t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(table));
if (t.next()) {
QStringList fNames = t.value(2).toString().simplified().split(QLatin1Char(','));
QRegExp regx(QLatin1String("\\s*(\\S+)(?:\\s+(DESC|desc))?\\s*"));
diff --git a/src/sql/kernel/qsqlcachedresult.cpp b/src/sql/kernel/qsqlcachedresult.cpp
index 3cace06..ca51dc0 100644
--- a/src/sql/kernel/qsqlcachedresult.cpp
+++ b/src/sql/kernel/qsqlcachedresult.cpp
@@ -294,4 +294,17 @@ QSqlCachedResult::ValueCache &QSqlCachedResult::cache()
return d->cache;
}
+void QSqlCachedResult::virtual_hook(int id, void *data)
+{
+ switch (id) {
+ case QSqlResult::DetachFromResultSet:
+ case QSqlResult::SetNumericalPrecision:
+ cleanup();
+ break;
+ default:
+ QSqlResult::virtual_hook(id, data);
+ }
+}
+
+
QT_END_NAMESPACE
diff --git a/src/sql/kernel/qsqlcachedresult_p.h b/src/sql/kernel/qsqlcachedresult_p.h
index d19435c..a384b2e 100644
--- a/src/sql/kernel/qsqlcachedresult_p.h
+++ b/src/sql/kernel/qsqlcachedresult_p.h
@@ -89,6 +89,7 @@ protected:
int colCount() const;
ValueCache &cache();
+ void virtual_hook(int id, void *data);
private:
bool cacheNext();
QSqlCachedResultPrivate *d;
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 1c1595d..93c9d9f 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -905,7 +905,6 @@ QVariant QSqlResult::lastInsertId() const
*/
void QSqlResult::virtual_hook(int, void *)
{
- Q_ASSERT(false);
}
/*! \internal
@@ -971,6 +970,7 @@ void QSqlResult::detachFromResultSet()
void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
{
d->precisionPolicy = policy;
+ virtual_hook(SetNumericalPrecision, &policy);
}
/*! \internal
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 1acc846..156af26 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -98,7 +98,10 @@ bool QSqlTableModelPrivate::setRecord(int row, const QSqlRecord &record)
int QSqlTableModelPrivate::nameToIndex(const QString &name) const
{
- return rec.indexOf(name);
+ QString fieldname = name;
+ if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName))
+ fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName);
+ return rec.indexOf(fieldname);
}
void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
@@ -367,10 +370,7 @@ void QSqlTableModel::setTable(const QString &tableName)
{
Q_D(QSqlTableModel);
clear();
- if(d->db.tables().contains(tableName.toUpper()))
- d->tableName = tableName.toUpper();
- else
- d->tableName = tableName;
+ d->tableName = tableName;
d->initRecordAndPrimaryIndex();
d->initColOffsets(d->rec.count());
@@ -976,7 +976,9 @@ QString QSqlTableModel::orderByClause() const
if (!f.isValid())
return s;
- QString table = d->db.driver()->escapeIdentifier(d->tableName, QSqlDriver::TableName);
+ QString table = d->tableName;
+ //we can safely escape the field because it would have been obtained from the database
+ //and have the correct case
QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);
s.append(QLatin1String("ORDER BY ")).append(table).append(QLatin1Char('.')).append(field);
s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC");
@@ -1317,8 +1319,12 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &record)
mrow.rec = d->rec;
mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row());
}
+ QString fieldName;
for (int i = 0; i < record.count(); ++i) {
- int idx = mrow.rec.indexOf(record.fieldName(i));
+ fieldName = record.fieldName(i);
+ if (d->db.driver()->isIdentifierEscaped(fieldName, QSqlDriver::FieldName))
+ fieldName = d->db.driver()->stripDelimiters(fieldName, QSqlDriver::FieldName);
+ int idx = mrow.rec.indexOf(fieldName);
if (idx == -1)
isOk = false;
else
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp
index 6782429..e09f382 100644
--- a/src/svg/qsvggraphics.cpp
+++ b/src/svg/qsvggraphics.cpp
@@ -198,9 +198,8 @@ QRectF QSvgPath::bounds() const
}
QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly)
- : QSvgNode(parent), m_poly(poly)
+ : QSvgNode(parent), m_poly(poly), m_fillRule(Qt::WindingFill)
{
-
}
QRectF QSvgPolygon::bounds() const
@@ -217,7 +216,7 @@ QRectF QSvgPolygon::bounds() const
void QSvgPolygon::draw(QPainter *p, QSvgExtraStates &states)
{
- QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly));
+ QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, m_fillRule));
}
diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h
index 8a412c4..4a19c7e 100644
--- a/src/svg/qsvggraphics_p.h
+++ b/src/svg/qsvggraphics_p.h
@@ -155,8 +155,13 @@ public:
virtual void draw(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
virtual QRectF bounds() const;
+ void setFillRule(Qt::FillRule f)
+ {
+ m_fillRule = f;
+ }
private:
QPolygonF m_poly;
+ Qt::FillRule m_fillRule;
};
class QSvgPolyline : public QSvgNode
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index e2c1312..345dcf3 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -497,10 +497,8 @@ static bool constructColor(const QString &colorStr, const QString &opacity,
if (!resolveColor(colorStr, color, handler))
return false;
if (!opacity.isEmpty()) {
- qreal op = toDouble(opacity);
- if (op <= 1)
- op *= 255;
- color.setAlpha(int(op));
+ qreal op = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
+ color.setAlphaF(op);
}
return true;
}
@@ -641,15 +639,22 @@ static void parseBrush(QSvgNode *node,
f = Qt::OddEvenFill;
if (value.startsWith(QLatin1String("url"))) {
value = value.remove(0, 3);
+ QSvgFillStyle *prop = new QSvgFillStyle(0);
QSvgStyleProperty *style = styleFromUrl(node, value);
if (style) {
- QSvgFillStyle *prop = new QSvgFillStyle(style);
- if (!opacity.isEmpty())
- prop->setFillOpacity(toDouble(opacity));
- node->appendStyleProperty(prop, myId);
+ prop->setFillStyle(style);
} else {
- qWarning("Couldn't resolve property: %s", qPrintable(idFromUrl(value)));
+ QString id = idFromUrl(value);
+ prop->setGradientId(id);
+ prop->setGradientResolved(false);
}
+ if (!opacity.isEmpty()) {
+ qreal clampedOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
+ prop->setFillOpacity(clampedOpacity);
+ }
+ if (!fillRule.isEmpty())
+ prop->setFillRule(f);
+ node->appendStyleProperty(prop,myId);
} else if (value != QLatin1String("none")) {
QColor color;
if (constructColor(value, opacity, color, handler)) {
@@ -1377,6 +1382,11 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
y = y0 = arg[1] + offsetY;
path.moveTo(x0, y0);
arg.pop_front(); arg.pop_front();
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('l');
}
break;
case 'M': {
@@ -1389,6 +1399,11 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
path.moveTo(x0, y0);
arg.pop_front(); arg.pop_front();
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('L');
}
break;
case 'z':
@@ -1943,7 +1958,7 @@ static void parseOpacity(QSvgNode *node,
qreal op = value.toDouble(&ok);
if (ok) {
- QSvgOpacityStyle *opacity = new QSvgOpacityStyle(op);
+ QSvgOpacityStyle *opacity = new QSvgOpacityStyle(qMin(qreal(1.0), qMax(qreal(0.0), op)));
node->appendStyleProperty(opacity, someId(attributes));
}
}
@@ -3570,8 +3585,34 @@ bool QSvgHandler::endElement(const QStringRef &localName)
node->popFormat();
}
- if (node == Graphics)
+ if (node == Graphics) {
+ // Iterate through the m_renderers to resolve any unresolved gradients.
+ QSvgNode* curNode = static_cast<QSvgNode*>(m_nodes.top());
+ if (curNode->type() == QSvgNode::DOC ||
+ curNode->type() == QSvgNode::G ||
+ curNode->type() == QSvgNode::DEFS ||
+ curNode->type() == QSvgNode::SWITCH) {
+ QSvgStructureNode* structureNode = static_cast<QSvgStructureNode*>(curNode);
+ QList<QSvgNode*> ren = structureNode->renderers();
+ QList<QSvgNode*>::iterator itr = ren.begin();
+ while (itr != ren.end()) {
+ QSvgNode *eleNode = *itr++;
+ QSvgFillStyle *prop = static_cast<QSvgFillStyle*>(eleNode->styleProperty(QSvgStyleProperty::FILL));
+ if (prop && !(prop->isGradientResolved())) {
+ QString id = prop->getGradientId();
+ QSvgStyleProperty *style = structureNode->scopeStyle(id);
+ if (style) {
+ prop->setFillStyle(style);
+ } else {
+ qWarning("Couldn't resolve property : %s",qPrintable(id));
+ prop->setBrush(QBrush(Qt::NoBrush));
+ }
+ }
+ }
+ }
m_nodes.pop();
+ }
+
else if (m_style && !m_skipNodes.isEmpty() && m_skipNodes.top() != Style)
m_style = 0;
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
index 67a21bf..c1ad4bf 100644
--- a/src/svg/qsvgstructure.cpp
+++ b/src/svg/qsvgstructure.cpp
@@ -68,13 +68,11 @@ void QSvgG::draw(QPainter *p, QSvgExtraStates &states)
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
- if (displayMode() != QSvgNode::NoneMode) {
- while (itr != m_renderers.end()) {
- QSvgNode *node = *itr;
- if (node->isVisible())
- node->draw(p, states);
- ++itr;
- }
+ while (itr != m_renderers.end()) {
+ QSvgNode *node = *itr;
+ if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
+ node->draw(p, states);
+ ++itr;
}
revertStyle(p, states);
}
@@ -321,63 +319,61 @@ void QSvgSwitch::draw(QPainter *p, QSvgExtraStates &states)
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
- if (displayMode() != QSvgNode::NoneMode) {
- while (itr != m_renderers.end()) {
- QSvgNode *node = *itr;
- if (node->isVisible()) {
- const QStringList &features = node->requiredFeatures();
- const QStringList &extensions = node->requiredExtensions();
- const QStringList &languages = node->requiredLanguages();
- const QStringList &formats = node->requiredFormats();
- const QStringList &fonts = node->requiredFonts();
-
- bool okToRender = true;
- if (!features.isEmpty()) {
- QStringList::const_iterator sitr = features.constBegin();
- for (; sitr != features.constEnd(); ++sitr) {
- if (!isSupportedSvgFeature(*sitr)) {
- okToRender = false;
- break;
- }
+ while (itr != m_renderers.end()) {
+ QSvgNode *node = *itr;
+ if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) {
+ const QStringList &features = node->requiredFeatures();
+ const QStringList &extensions = node->requiredExtensions();
+ const QStringList &languages = node->requiredLanguages();
+ const QStringList &formats = node->requiredFormats();
+ const QStringList &fonts = node->requiredFonts();
+
+ bool okToRender = true;
+ if (!features.isEmpty()) {
+ QStringList::const_iterator sitr = features.constBegin();
+ for (; sitr != features.constEnd(); ++sitr) {
+ if (!isSupportedSvgFeature(*sitr)) {
+ okToRender = false;
+ break;
}
}
+ }
- if (okToRender && !extensions.isEmpty()) {
- QStringList::const_iterator sitr = extensions.constBegin();
- for (; sitr != extensions.constEnd(); ++sitr) {
- if (!isSupportedSvgExtension(*sitr)) {
- okToRender = false;
- break;
- }
+ if (okToRender && !extensions.isEmpty()) {
+ QStringList::const_iterator sitr = extensions.constBegin();
+ for (; sitr != extensions.constEnd(); ++sitr) {
+ if (!isSupportedSvgExtension(*sitr)) {
+ okToRender = false;
+ break;
}
}
+ }
- if (okToRender && !languages.isEmpty()) {
- QStringList::const_iterator sitr = languages.constBegin();
- okToRender = false;
- for (; sitr != languages.constEnd(); ++sitr) {
- if ((*sitr).startsWith(m_systemLanguagePrefix)) {
- okToRender = true;
- break;
- }
+ if (okToRender && !languages.isEmpty()) {
+ QStringList::const_iterator sitr = languages.constBegin();
+ okToRender = false;
+ for (; sitr != languages.constEnd(); ++sitr) {
+ if ((*sitr).startsWith(m_systemLanguagePrefix)) {
+ okToRender = true;
+ break;
}
}
+ }
- if (okToRender && !formats.isEmpty()) {
- okToRender = false;
- }
+ if (okToRender && !formats.isEmpty()) {
+ okToRender = false;
+ }
- if (okToRender && !fonts.isEmpty()) {
- okToRender = false;
- }
+ if (okToRender && !fonts.isEmpty()) {
+ okToRender = false;
+ }
- if (okToRender) {
- node->draw(p, states);
- break;
- }
+ if (okToRender) {
+ node->draw(p, states);
+ break;
}
- ++itr;
}
+ ++itr;
}
revertStyle(p, states);
}
diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp
index fa996f4..fec6231 100644
--- a/src/svg/qsvgstyle.cpp
+++ b/src/svg/qsvgstyle.cpp
@@ -81,12 +81,12 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &)
}
QSvgFillStyle::QSvgFillStyle(const QBrush &brush)
- : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false)
+ : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
{
}
QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style)
- : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false)
+ : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
{
}
@@ -107,6 +107,9 @@ static void recursivelySetFill(QSvgNode *node, Qt::FillRule f)
if (node->type() == QSvgNode::PATH) {
QSvgPath *path = static_cast<QSvgPath*>(node);
path->qpath()->setFillRule(f);
+ } else if (node->type() == QSvgNode::POLYGON) {
+ QSvgPolygon *polygon = static_cast<QSvgPolygon*>(node);
+ polygon->setFillRule(f);
} else if (node->type() == QSvgNode::G) {
QList<QSvgNode*> renderers = static_cast<QSvgG*>(node)->renderers();
foreach(QSvgNode *n, renderers) {
diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h
index 4bbc6cf..e65b6f5 100644
--- a/src/svg/qsvgstyle_p.h
+++ b/src/svg/qsvgstyle_p.h
@@ -229,6 +229,38 @@ public:
{
return m_fill;
}
+
+ void setGradientId(const QString &Id)
+ {
+ m_gradientId = Id;
+ }
+
+ QString getGradientId() const
+ {
+ return m_gradientId;
+ }
+
+
+ void setGradientResolved(bool resolved)
+ {
+ m_gradientResolved = resolved;
+ }
+
+ bool isGradientResolved() const
+ {
+ return m_gradientResolved;
+ }
+
+ void setFillStyle(QSvgStyleProperty* style)
+ {
+ m_style = style;
+ }
+
+ void setBrush(QBrush brush)
+ {
+ m_fill = brush;
+ }
+
private:
// fill v v 'inherit' | <Paint.datatype>
// fill-opacity v v 'inherit' | <OpacityValue.datatype>
@@ -241,6 +273,8 @@ private:
bool m_fillOpacitySet;
qreal m_fillOpacity;
qreal m_oldOpacity;
+ QString m_gradientId;
+ bool m_gradientResolved;
};
class QSvgViewportFillStyle : public QSvgStyleProperty
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index de214bb..3058569 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -231,8 +231,10 @@ void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
m_time.start();
}
- p->save();
+ if (displayMode() == QSvgNode::NoneMode)
+ return;
+ p->save();
//sets default style on the painter
//### not the most optimal way
mapSourceToTarget(p, bounds);
@@ -244,7 +246,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
applyStyle(p, m_states);
while (itr != m_renderers.end()) {
QSvgNode *node = *itr;
- if (node->isVisible())
+ if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
node->draw(p, m_states);
++itr;
}
@@ -262,6 +264,12 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id,
qDebug("Couldn't find node %s. Skipping rendering.", qPrintable(id));
return;
}
+ if (m_time.isNull()) {
+ m_time.start();
+ }
+
+ if (node->displayMode() == QSvgNode::NoneMode)
+ return;
p->save();
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 4a9675a..64c1312 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -139,7 +139,7 @@ namespace QTest {
if (!counter.deref()) {
QTest::testLogger->addMessage(QAbstractTestLogger::QSystem,
- "Maximum amount of warnings exceeded.");
+ "Maximum amount of warnings exceeded. Use -maxwarnings to override.");
return;
}
}
diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp
index 7e42da8..5e5bd39 100644
--- a/tests/auto/qpainter/tst_qpainter.cpp
+++ b/tests/auto/qpainter/tst_qpainter.cpp
@@ -202,6 +202,7 @@ private slots:
void drawImage_task217400_data();
void drawImage_task217400();
+ void drawImage_1x1();
void drawRect_task215378();
void drawRect_task247505();
@@ -4237,5 +4238,25 @@ void tst_QPainter::emptyClip()
p.fillPath(path, Qt::green);
}
+void tst_QPainter::drawImage_1x1()
+{
+ QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
+ source.fill(0xffffffff);
+
+ QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0xff000000);
+ QPainter p(&img);
+ p.drawImage(QRectF(0.9, 0.9, 32, 32), source);
+ p.end();
+
+ QImage expected = img;
+ expected.fill(0xff000000);
+ p.begin(&expected);
+ p.fillRect(1, 1, 31, 31, Qt::white);
+ p.end();
+
+ QCOMPARE(img, expected);
+}
+
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"
diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h
index 77d1d5b..a490a2f 100644
--- a/tests/auto/qsqldatabase/tst_databases.h
+++ b/tests/auto/qsqldatabase/tst_databases.h
@@ -105,11 +105,7 @@ inline static QString qTableName( const QString& prefix, QSqlDriver* driver = 0
inline static bool testWhiteSpaceNames( const QString &name )
{
-/* return name.startsWith( "QPSQL" )
- || name.startsWith( "QODBC" )
- || name.startsWith( "QSQLITE" )
- || name.startsWith( "QMYSQL" );*/
- return name != QLatin1String("QSQLITE2");
+ return name != QLatin1String("QTDS7");
}
inline static QString toHex( const QString& binary )
@@ -211,7 +207,7 @@ public:
// This requires a local ODBC data source to be configured( pointing to a MySql database )
// addDb( "QODBC", "mysqlodbc", "troll", "trond" );
// addDb( "QODBC", "SqlServer", "troll", "trond" );
-// addDb( "QTDS7", "testdb", "troll", "trondk", "horsehead.nokia.troll.no" );
+// addDb( "QTDS7", "testdb", "troll", "trondk", "horsehead" );
// addDb( "QODBC", "silencetestdb", "troll", "trond", "silence" );
// addDb( "QODBC", "horseheadtestdb", "troll", "trondk", "horsehead" );
@@ -221,7 +217,7 @@ public:
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3309, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 5.0.18 Linux
// addDb( "QMYSQL3", "testdb", "troll", "trond", "iceblink.nokia.troll.no" ); // MySQL 5.0.13 Windows
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql4-nokia.trolltech.com.au" ); // MySQL 4.1.22-2.el4 linux
-// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux
+// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no" ); // V7.2 NOT SUPPORTED!
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5434 ); // V7.2 NOT SUPPORTED! Multi-byte
@@ -242,17 +238,17 @@ public:
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "firebird2-nokia.trolltech.com.au" ); // Firebird 2.1.1
// use in-memory database to prevent local files
-// addDb("QSQLITE", ":memory:");
- addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") );
+ addDb("QSQLITE", ":memory:");
+// addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") );
// addDb( "QSQLITE2", QDir::toNativeSeparators(QDir::tempPath()+"/foo2.db") );
// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=iceblink.nokia.troll.no\\ICEBLINK", "troll", "trond", "" );
// addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" );
// addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
-// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" );
-// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" );
-// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_", "testuser", "Ee4Gabf6_", "" );
-// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_", "testuser", "Ee4Gabf6_", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk;TDS_Version=8.0", "troll", "trondk", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond;TDS_Version=8.0", "troll", "trond", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" );
// addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" );
// addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" );
}
@@ -320,16 +316,18 @@ public:
QSqlQuery q( db );
QStringList dbtables=db.tables();
- foreach(const QString &tableName, tableNames) {
+ foreach(QString tableName, tableNames)
+ {
wasDropped = true;
- foreach(const QString dbtablesName, dbtables) {
- if(dbtablesName.toUpper() == tableName.toUpper()) {
- dbtables.removeAll(dbtablesName);
- wasDropped = q.exec("drop table " + db.driver()->escapeIdentifier( dbtablesName, QSqlDriver::TableName ));
- if(!wasDropped)
- wasDropped = q.exec("drop table " + dbtablesName);
- }
- }
+ QString table=tableName;
+ if ( db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName))
+ table = db.driver()->stripDelimiters(table, QSqlDriver::TableName);
+
+ if ( dbtables.contains( table, Qt::CaseSensitive ) )
+ wasDropped = q.exec( "drop table " + tableName);
+ else if ( dbtables.contains( table, Qt::CaseInsensitive ) )
+ wasDropped = q.exec( "drop table " + tableName);
+
if ( !wasDropped )
qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError().text() << "tables:" << dbtables;
}
diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp
index 13ec263..cce4602 100644
--- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp
@@ -1625,7 +1625,7 @@ void tst_QSqlDatabase::precisionPolicy()
q.bindValue(1, 123);
QVERIFY_SQL(q, exec());
q.bindValue(0, 2);
- q.bindValue(1, QString("1850000000000.0001"));
+ q.bindValue(1, 1850000000000.0001);
QVERIFY_SQL(q, exec());
// These are expected to pass
@@ -1633,29 +1633,39 @@ void tst_QSqlDatabase::precisionPolicy()
QString query = QString("SELECT num FROM %1 WHERE id = 1").arg(tableName);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::String);
q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(q.value(0).type() != QVariant::LongLong)
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::LongLong);
QCOMPARE(q.value(0).toLongLong(), (qlonglong)123);
q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt32);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::Int);
QCOMPARE(q.value(0).toInt(), 123);
q.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::Double);
QCOMPARE(q.value(0).toDouble(), (double)123);
query = QString("SELECT num FROM %1 WHERE id = 2").arg(tableName);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::Double);
QCOMPARE(q.value(0).toDouble(), QString("1850000000000.0001").toDouble());
@@ -1663,21 +1673,27 @@ void tst_QSqlDatabase::precisionPolicy()
q.setNumericalPrecisionPolicy(QSql::HighPrecision);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::String);
q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64);
QEXPECT_FAIL("QOCI", "Oracle fails here, to retrieve next", Continue);
QVERIFY_SQL(q, exec(query));
QVERIFY_SQL(q, next());
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
QCOMPARE(q.value(0).type(), QVariant::LongLong);
QSql::NumericalPrecisionPolicy oldPrecision= db.numericalPrecisionPolicy();
- db.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble);
+ db.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64);
QSqlQuery q2(db);
q2.exec(QString("SELECT num FROM %1 WHERE id = 2").arg(tableName));
QVERIFY_SQL(q2, exec(query));
QVERIFY_SQL(q2, next());
- QCOMPARE(q2.value(0).type(), QVariant::Double);
+ if(db.driverName().startsWith("QSQLITE"))
+ QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue);
+ QCOMPARE(q2.value(0).type(), QVariant::LongLong);
db.setNumericalPrecisionPolicy(oldPrecision);
}
diff --git a/tests/auto/qsqldriver/qsqldriver.pro b/tests/auto/qsqldriver/qsqldriver.pro
new file mode 100644
index 0000000..0024841
--- /dev/null
+++ b/tests/auto/qsqldriver/qsqldriver.pro
@@ -0,0 +1,16 @@
+load(qttest_p4)
+SOURCES += tst_qsqldriver.cpp
+
+QT += sql
+
+wince*: {
+ plugFiles.sources = ../../../plugins/sqldrivers
+ plugFiles.path = .
+ DEPLOYMENT += plugFiles
+} else {
+ win32-g++ {
+ LIBS += -lws2_32
+ } else:win32 {
+ LIBS += ws2_32.lib
+ }
+}
diff --git a/tests/auto/qsqldriver/tst_qsqldriver.cpp b/tests/auto/qsqldriver/tst_qsqldriver.cpp
new file mode 100644
index 0000000..bbd7483
--- /dev/null
+++ b/tests/auto/qsqldriver/tst_qsqldriver.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtSql/QtSql>
+
+#include "../qsqldatabase/tst_databases.h"
+
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSqlDriver : public QObject
+{
+ Q_OBJECT
+
+public:
+ void recreateTestTables(QSqlDatabase);
+
+ tst_Databases dbs;
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void record();
+ void primaryIndex();
+};
+
+
+void tst_QSqlDriver::initTestCase_data()
+{
+ dbs.open();
+ if (dbs.fillTestTable() == 0) {
+ qWarning("NO DATABASES");
+ QSKIP("No database drivers are available in this Qt configuration", SkipAll);
+ }
+}
+
+void tst_QSqlDriver::recreateTestTables(QSqlDatabase db)
+{
+ QSqlQuery q(db);
+
+ QStringList tableNames;
+ tableNames << qTableName( "relTEST1" );
+ tst_Databases::safeDropTables( db, tableNames );
+
+ QVERIFY_SQL( q, exec("create table " + qTableName("relTEST1") +
+ " (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("relTEST1") + " values(1, 'harry', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("relTEST1") + " values(2, 'trond', 2, 1)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("relTEST1") + " values(3, 'vohi', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("relTEST1") + " values(4, 'boris', 2, 2)"));
+}
+
+void tst_QSqlDriver::initTestCase()
+{
+ foreach (const QString &dbname, dbs.dbNames)
+ recreateTestTables(QSqlDatabase::database(dbname));
+}
+
+void tst_QSqlDriver::cleanupTestCase()
+{
+ QStringList tableNames;
+ tableNames << qTableName( "relTEST1" );
+ foreach (const QString &dbName, dbs.dbNames) {
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ tst_Databases::safeDropTables( db, tableNames );
+ }
+ dbs.close();
+}
+
+void tst_QSqlDriver::init()
+{
+}
+
+void tst_QSqlDriver::cleanup()
+{
+}
+
+void tst_QSqlDriver::record()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QString tablename = qTableName("relTEST1");
+ QStringList fields;
+ fields << "id" << "name" << "title_key" << "another_title_key";
+
+ //check we can get records using an unquoted mixed case table name
+ QSqlRecord rec = db.driver()->record(tablename);
+ QCOMPARE(rec.count(), 4);
+
+ if (db.driverName().startsWith("QIBASE")|| db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ for(int i = 0; i < fields.count(); ++i)
+ fields[i] = fields[i].toUpper();
+
+ for (int i = 0; i < fields.count(); ++i)
+ QCOMPARE(rec.fieldName(i), fields[i]);
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ tablename = tablename.toUpper();
+ else if (db.driverName().startsWith("QPSQL"))
+ tablename = tablename.toLower();
+
+ //check we can get records using a properly quoted table name
+ rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName));
+ QCOMPARE(rec.count(), 4);
+
+ for (int i = 0; i < fields.count(); ++i)
+ QCOMPARE(rec.fieldName(i), fields[i]);
+
+ if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ tablename = tablename.toLower();
+ else if (db.driverName().startsWith("QPSQL"))
+ tablename = tablename.toUpper();
+
+ //check that we can't get records using incorrect tablename casing that's been quoted
+ rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName));
+ if (db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS"))
+ QCOMPARE(rec.count(), 4); //mysql, sqlite and tds will match
+ else
+ QCOMPARE(rec.count(), 0);
+
+}
+
+void tst_QSqlDriver::primaryIndex()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QString tablename = qTableName("relTEST1");
+ //check that we can get primary index using unquoted mixed case table name
+ QSqlIndex index = db.driver()->primaryIndex(tablename);
+ QCOMPARE(index.count(), 1);
+
+ if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ QCOMPARE(index.fieldName(0), QString::fromLatin1("ID"));
+ else
+ QCOMPARE(index.fieldName(0), QString::fromLatin1("id"));
+
+
+ //check that we can get the primary index using a quoted tablename
+ if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ tablename = tablename.toUpper();
+ else if (db.driverName().startsWith("QPSQL"))
+ tablename = tablename.toLower();
+
+ index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName));
+ QCOMPARE(index.count(), 1);
+ if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ QCOMPARE(index.fieldName(0), QString::fromLatin1("ID"));
+ else
+ QCOMPARE(index.fieldName(0), QString::fromLatin1("id"));
+
+
+
+ //check that we can not get the primary index using a quoted but incorrect table name casing
+ if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ tablename = tablename.toLower();
+ else if (db.driverName().startsWith("QPSQL"))
+ tablename = tablename.toUpper();
+
+ index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName));
+ if (db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS"))
+ QCOMPARE(index.count(), 1); //mysql will always find the table name regardless of casing
+ else
+ QCOMPARE(index.count(), 0);
+}
+
+QTEST_MAIN(tst_QSqlDriver)
+#include "tst_qsqldriver.moc"
diff --git a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
index 5725548..4588af8 100644
--- a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
+++ b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
@@ -82,6 +82,10 @@ private slots:
void insertRecordDuplicateFieldNames();
void invalidData();
void relationModel();
+ void casing();
+ void escapedRelations();
+ void escapedTableName();
+ void whiteSpaceInIdentifiers();
};
@@ -103,7 +107,9 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
<< qTableName( "reltest2" )
<< qTableName( "reltest3" )
<< qTableName( "reltest4" )
- << qTableName( "reltest5" );
+ << qTableName( "reltest5" )
+ << db.driver()->escapeIdentifier(qTableName( "rel test6" ), QSqlDriver::TableName)
+ << db.driver()->escapeIdentifier(qTableName( "rel test7" ), QSqlDriver::TableName);
tst_Databases::safeDropTables( db, tableNames );
QVERIFY_SQL( q, exec("create table " + qTableName("reltest1") +
@@ -128,6 +134,19 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
QVERIFY_SQL( q, exec("create table " + qTableName("reltest5") + " (title varchar(20) not null primary key, abbrev varchar(20))"));
QVERIFY_SQL( q, exec("insert into " + qTableName("reltest5") + " values('herr', 'Hr')"));
QVERIFY_SQL( q, exec("insert into " + qTableName("reltest5") + " values('mister', 'Mr')"));
+
+ if (testWhiteSpaceNames(db.driverName())) {
+ QString reltest6 = db.driver()->escapeIdentifier(qTableName("rel test6"), QSqlDriver::TableName);
+ QVERIFY_SQL( q, exec("create table " + reltest6 + " (id int not null primary key, " + db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName) +
+ " int, " + db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName) + " int)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(1, 1,9)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(2, 2,8)"));
+
+ QString reltest7 = db.driver()->escapeIdentifier(qTableName("rel test7"), QSqlDriver::TableName);
+ QVERIFY_SQL( q, exec("create table " + reltest7 + " (" + db.driver()->escapeIdentifier("city id", QSqlDriver::TableName) + " int not null primary key, " + db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName) + " varchar(20))"));
+ QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(1, 'New York')"));
+ QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(2, 'Washington')"));
+ }
}
void tst_QSqlRelationalTableModel::initTestCase()
@@ -142,10 +161,14 @@ void tst_QSqlRelationalTableModel::cleanupTestCase()
tableNames << qTableName( "reltest1" )
<< qTableName( "reltest2" )
<< qTableName( "reltest3" )
- << qTableName( "reltest4" );
+ << qTableName( "reltest4" )
+ << qTableName( "reltest5" );
foreach (const QString &dbName, dbs.dbNames) {
QSqlDatabase db = QSqlDatabase::database(dbName);
- tst_Databases::safeDropTables( db, tableNames );
+ QStringList tables = tableNames;
+ tables << db.driver()->escapeIdentifier(qTableName( "rel test6" ), QSqlDriver::TableName)
+ << db.driver()->escapeIdentifier(qTableName( "rel test7" ), QSqlDriver::TableName);
+ tst_Databases::safeDropTables( db, tables );
}
dbs.close();
}
@@ -273,7 +296,12 @@ void tst_QSqlRelationalTableModel::setData()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+
+ //sybase doesn't allow tables with the same alias used twice as col names
+ //so don't set up an identical relation when using the tds driver
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
@@ -284,7 +312,10 @@ void tst_QSqlRelationalTableModel::setData()
QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi2"));
QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
QVERIFY_SQL(model, submitAll());
}
@@ -299,10 +330,15 @@ void tst_QSqlRelationalTableModel::setData()
QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
}
//check setting of data when the relational key is a non-integer type
@@ -336,7 +372,8 @@ void tst_QSqlRelationalTableModel::multipleRelation()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ model.setRelation(3, QSqlRelation(qTableName("reltest4"), "id", "name"));
+ model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
@@ -344,7 +381,7 @@ void tst_QSqlRelationalTableModel::multipleRelation()
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("Trondheim"));
}
void tst_QSqlRelationalTableModel::insertRecord()
@@ -357,6 +394,7 @@ void tst_QSqlRelationalTableModel::insertRecord()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
QSqlRecord rec;
@@ -398,6 +436,7 @@ void tst_QSqlRelationalTableModel::setRecord()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
QSqlRecord rec;
@@ -450,13 +489,18 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0,0)).toInt(), 1);
QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0,2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
model.insertRows(0, 1);
model.setData(model.index(0, 0), 1011);
@@ -467,12 +511,20 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
QCOMPARE(model.data(model.index(0,0)).toInt(), 1011);
QCOMPARE(model.data(model.index(0,1)).toString(), QString("test"));
QCOMPARE(model.data(model.index(0,2)).toString(), QString("mister"));
- QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 1);
QCOMPARE(model.data(model.index(1,0)).toInt(), 1);
QCOMPARE(model.data(model.index(1,1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(1,2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(1,3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(1,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(1,3)).toInt(), 2);
+
+
QVERIFY_SQL(model, submitAll());
@@ -481,9 +533,16 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
QCOMPARE(model.data(model.index(0,0)).toInt(), 1);
QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0,2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
- model.setData(model.index(0,3),1);
- QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+
+ if (!db.driverName().startsWith("QTDS")) {
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ model.setData(model.index(0,3),1);
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+ } else {
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
+ model.setData(model.index(0,3),1);
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 1);
+ }
model.insertRows(0, 2);
model.setData(model.index(0, 0), 1012);
@@ -499,17 +558,27 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
QCOMPARE(model.data(model.index(0,0)).toInt(),1012);
QCOMPARE(model.data(model.index(0,1)).toString(), QString("george"));
QCOMPARE(model.data(model.index(0,2)).toString(), QString("mister"));
- QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
+
QCOMPARE(model.data(model.index(1,0)).toInt(),1013);
QCOMPARE(model.data(model.index(1,1)).toString(), QString("kramer"));
QCOMPARE(model.data(model.index(1,2)).toString(), QString("mister"));
- QCOMPARE(model.data(model.index(1,3)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(1,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(1,3)).toInt(), 1);
QCOMPARE(model.data(model.index(2,0)).toInt(), 1);
QCOMPARE(model.data(model.index(2,1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(2,2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(2,3)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(2,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(2,3)).toInt(), 1);
QVERIFY_SQL(model, submitAll());
}
@@ -574,7 +643,8 @@ void tst_QSqlRelationalTableModel::sort()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
model.setSort(2, Qt::DescendingOrder);
QVERIFY_SQL(model, select());
@@ -589,11 +659,19 @@ void tst_QSqlRelationalTableModel::sort()
model.setSort(3, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
- QCOMPARE(model.rowCount(), 4);
- QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(1, 3)).toString(), QString("mister"));
- QCOMPARE(model.data(model.index(2, 3)).toString(), QString("mister"));
- QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS")) {
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(1, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(2, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ } else {
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 3)).toInt(), 2);
+ }
+
}
static void testRevert(QSqlRelationalTableModel &model)
@@ -663,7 +741,7 @@ void tst_QSqlRelationalTableModel::revert()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ model.setRelation(3, QSqlRelation(qTableName("reltest4"), "id", "name"));
model.setSort(0, Qt::AscendingOrder);
@@ -689,7 +767,9 @@ void tst_QSqlRelationalTableModel::clearDisplayValuesCache()
model.setTable(qTableName("reltest1"));
model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
model.setSort(1, Qt::AscendingOrder);
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
@@ -698,7 +778,10 @@ void tst_QSqlRelationalTableModel::clearDisplayValuesCache()
QCOMPARE(model.data(model.index(3, 0)).toInt(), 3);
QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(3, 3)).toInt(), 2 );
model.insertRow(model.rowCount());
QVERIFY(model.setData(model.index(4, 0), 5, Qt::EditRole));
@@ -710,11 +793,18 @@ void tst_QSqlRelationalTableModel::clearDisplayValuesCache()
QCOMPARE(model.data(model.index(0, 0)).toInt(), 5);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("anders"));
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+
QCOMPARE(model.data(model.index(4, 0)).toInt(), 3);
QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
QCOMPARE(model.data(model.index(4, 2)).toString(), QString("herr"));
- QCOMPARE(model.data(model.index(4, 3)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(4, 3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(4, 3)).toInt(), 2);
}
// For task 140782 and 176374: If the main table and the the related tables uses the same
@@ -729,27 +819,38 @@ void tst_QSqlRelationalTableModel::insertRecordDuplicateFieldNames()
QSqlRelationalTableModel model(0, db);
model.setTable(qTableName("reltest3"));
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setSort(0, Qt::AscendingOrder);
// Duplication of "name", used in both reltest3 and reltest4.
model.setRelation(2, QSqlRelation(qTableName("reltest4"), "id", "name"));
QVERIFY_SQL(model, select());
- QCOMPARE(model.record(1).value(qTableName("reltest4").append(QLatin1String("_name"))).toString(),
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ QCOMPARE(model.record(1).value(qTableName("reltest4").append(QLatin1String("_name")).toUpper()).toString(),
+ QString("Trondheim"));
+ } else {
+ QCOMPARE(model.record(1).value(qTableName("reltest4").append(QLatin1String("_name"))).toString(),
QString("Trondheim"));
+ }
QSqlRecord rec = model.record();
rec.setValue(0, 3);
rec.setValue(1, "Berge");
rec.setValue(2, 1); // Must insert the key value
- QCOMPARE(rec.fieldName(0), QLatin1String("id"));
- QCOMPARE(rec.fieldName(1), QLatin1String("name")); // This comes from main table
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ QCOMPARE(rec.fieldName(0), QLatin1String("ID"));
+ QCOMPARE(rec.fieldName(1), QLatin1String("NAME")); // This comes from main table
+ } else {
+ QCOMPARE(rec.fieldName(0), QLatin1String("id"));
+ QCOMPARE(rec.fieldName(1), QLatin1String("name"));
+ }
// The duplicate field names is aliased because it's comes from the relation's display column.
- if(!db.driverName().startsWith("QIBASE"))
- QCOMPARE(rec.fieldName(2), qTableName("reltest4").append(QLatin1String("_name")));
- else
+ if(db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
QCOMPARE(rec.fieldName(2), (qTableName("reltest4").append(QLatin1String("_name"))).toUpper());
+ else
+ QCOMPARE(rec.fieldName(2), qTableName("reltest4").append(QLatin1String("_name")));
QVERIFY(model.insertRecord(-1, rec));
QCOMPARE(model.data(model.index(2, 2)).toString(), QString("Oslo"));
@@ -793,7 +894,7 @@ void tst_QSqlRelationalTableModel::relationModel()
QVERIFY(model.relationModel(3) == NULL);
QVERIFY(model.relationModel(4) == NULL);
- model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ model.setRelation(3, QSqlRelation(qTableName("reltest4"), "id", "name"));
QVERIFY_SQL(model, select());
QVERIFY(model.relationModel(0) == NULL);
@@ -806,5 +907,285 @@ void tst_QSqlRelationalTableModel::relationModel()
QCOMPARE(rel_model->data(rel_model->index(0,1)).toString(), QString("herr"));
}
+void tst_QSqlRelationalTableModel::casing()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (db.driverName().startsWith("QSQLITE"))
+ QSKIP("The casing test for SQLITE is irrelevant since SQLITE is case insensitive", SkipAll);
+
+ QStringList tableNames;
+ tableNames << qTableName("CASETEST1", db.driver()).toUpper();
+ tableNames << qTableName("casetest1", db.driver());
+ tst_Databases::safeDropTables(db, tableNames);
+
+ QSqlQuery q(db);
+ QVERIFY_SQL( q, exec("create table " + qTableName("CASETEST1", db.driver()).toUpper() +
+ " (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(1, 'harry', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(2, 'trond', 2, 1)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(3, 'vohi', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(4, 'boris', 2, 2)"));
+
+ QVERIFY_SQL( q, exec("create table " + qTableName("casetest1", db.driver()) +
+ " (ident int not null primary key, name varchar(20), title_key int)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(1, 'jerry', 1)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(2, 'george', 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(4, 'kramer', 2)"));
+
+ if (db.driverName().startsWith("QOCI")) {
+ //try an owner that doesn't exist
+ QSqlRecord rec = db.driver()->record("doug." + qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 0);
+
+ //try an owner that does exist
+ rec = db.driver()->record(db.userName() + "." + qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 4);
+ }
+ QSqlRecord rec = db.driver()->record(qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 4);
+
+ rec = db.driver()->record(qTableName("casetest1", db.driver()));
+ QCOMPARE( rec.count(), 3);
+
+ QSqlTableModel upperCaseModel(0, db);
+ upperCaseModel.setTable(qTableName("CASETEST1", db.driver()).toUpper());
+
+ QCOMPARE(upperCaseModel.tableName(),qTableName("CASETEST1",db.driver()).toUpper());
+
+ QVERIFY_SQL(upperCaseModel, select());
+
+ QCOMPARE(upperCaseModel.rowCount(), 4);
+
+ QSqlTableModel lowerCaseModel(0, db);
+ lowerCaseModel.setTable(qTableName("casetest1", db.driver()));
+ QCOMPARE(lowerCaseModel.tableName(), qTableName("casetest1",db.driver()));
+ QVERIFY_SQL(lowerCaseModel, select());
+
+ QCOMPARE(lowerCaseModel.rowCount(), 3);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(qTableName("CASETEST1", db.driver()).toUpper());
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ tst_Databases::safeDropTables(db, tableNames);
+}
+
+void tst_QSqlRelationalTableModel::escapedRelations()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(qTableName("reltest1"));
+
+ //try with relation table name quoted
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(qTableName("reltest2").toUpper(),QSqlDriver::TableName),
+ "tid",
+ "title"));
+ } else {
+ model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(qTableName("reltest2"),QSqlDriver::TableName),
+ "tid",
+ "title"));
+
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with index column quoted
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName).toUpper(),
+ "title"));
+ } else {
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName),
+ "title"));
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with display column quoted
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
+ } else {
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
+ }
+
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with tablename and index and display columns quoted in the relation
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
+ } else {
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"),
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::escapedTableName()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ // set the values using OnRowChange Strategy with an escaped tablename
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setTable(db.driver()->escapeIdentifier(qTableName("reltest1").toUpper(), QSqlDriver::TableName));
+ } else {
+ model.setTable(db.driver()->escapeIdentifier(qTableName("reltest1"), QSqlDriver::TableName));
+ }
+ model.setSort(0, Qt::AscendingOrder);
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(0, 1), QString("harry2")));
+ QVERIFY(model.setData(model.index(0, 2), 2));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+
+ model.submit();
+
+ QVERIFY(model.setData(model.index(3,1), QString("boris2")));
+ QVERIFY(model.setData(model.index(3, 2), 1));
+
+ QCOMPARE(model.data(model.index(3,1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+ model.submit();
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(qTableName("reltest1"));
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+
+ model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr"));
+
+ }
+}
+
+void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers() {
+
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (!testWhiteSpaceNames(db.driverName()))
+ QSKIP("White space test irrelevant for driver", SkipAll);
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(db.driver()->escapeIdentifier(qTableName("rel test6"), QSqlDriver::TableName));
+ model.setSort(0, Qt::DescendingOrder);
+ model.setRelation(1, QSqlRelation(db.driver()->escapeIdentifier(qTableName("rel test7"), QSqlDriver::TableName),
+ db.driver()->escapeIdentifier("city id", QSqlDriver::FieldName),
+ db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName)));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Washington"));
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("New York"));
+
+ QSqlRecord rec;
+ QSqlField f1("id", QVariant::Int);
+ QSqlField f2(db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName), QVariant::Int);
+ QSqlField f3(db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName), QVariant::Int);
+
+ f1.setValue(3);
+ f2.setValue(2);
+ f3.setValue(7);
+
+ f1.setGenerated(true);
+ f2.setGenerated(true);
+ f3.setGenerated(true);
+
+ rec.append(f1);
+ rec.append(f2);
+ rec.append(f3);
+
+ QVERIFY_SQL(model, insertRecord(-1, rec));
+ model.submitAll();
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Washington"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 7);
+
+ //TODO: For some reson setting a record using manual submit fails
+ //model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+ QSqlRecord recNew;
+ QSqlField f1New("id", QVariant::Int);
+ QSqlField f2New(db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName), QVariant::Int);
+ QSqlField f3New(db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName), QVariant::Int);
+
+ f1New.setValue(4);
+ f2New.setValue(1);
+ f3New.setValue(6);
+
+ f1New.setGenerated(true);
+ f2New.setGenerated(true);
+ f3New.setGenerated(true);
+
+ recNew.append(f1New);
+ recNew.append(f2New);
+ recNew.append(f3New);
+
+ QVERIFY_SQL(model, setRecord(0, recNew));
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 4);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("New York"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 6);
+
+ QVERIFY_SQL(model, submitAll());
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 4);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("New York"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 6);
+}
+
QTEST_MAIN(tst_QSqlRelationalTableModel)
#include "tst_qsqlrelationaltablemodel.moc"
diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp
index 5d1f9d4..aa882be 100644
--- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -145,7 +145,7 @@ void tst_QSqlTableModel::dropTestTables()
<< qTableName("bigtable")
<< qTableName("foo");
if (testWhiteSpaceNames(db.driverName()))
- tableNames << qTableName("qtestw hitespace");
+ tableNames << qTableName("qtestw hitespace", db.driver());
tst_Databases::safeDropTables(db, tableNames);
@@ -277,6 +277,7 @@ void tst_QSqlTableModel::setRecord()
QList<QSqlTableModel::EditStrategy> policies = QList<QSqlTableModel::EditStrategy>() << QSqlTableModel::OnFieldChange << QSqlTableModel::OnRowChange << QSqlTableModel::OnManualSubmit;
+ QString Xsuffix;
foreach( QSqlTableModel::EditStrategy submitpolicy, policies) {
QSqlTableModel model(0, db);
@@ -295,6 +296,8 @@ void tst_QSqlTableModel::setRecord()
if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit)
QVERIFY(model.submitAll());
+ else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1)
+ model.submit();
else {
// dataChanged() is not emitted when submitAll() is called
QCOMPARE(spy.count(), 2);
@@ -304,10 +307,12 @@ void tst_QSqlTableModel::setRecord()
}
}
- QCOMPARE(model.data(model.index(0, 1)).toString(), QString("fooX"));
- QCOMPARE(model.data(model.index(0, 2)).toString(), QString("barX"));
- QCOMPARE(model.data(model.index(1, 1)).toString(), QString("bazX"));
- QCOMPARE(model.data(model.index(1, 2)).toString(), QString("joeX"));
+ Xsuffix.append('X');
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("foo").append(Xsuffix));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("bar").append(Xsuffix));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("baz").append(Xsuffix));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("joe").append(Xsuffix));
}
}
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
index b39f0a1..553833c 100644
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp
@@ -118,6 +118,7 @@ private slots:
void postEvent();
void stateFinished();
void parallelStates();
+ void parallelRootState();
void allSourceToTargetConfigurations();
void signalTransitions();
void eventTransitions();
@@ -1633,6 +1634,29 @@ void tst_QStateMachine::parallelStates()
QVERIFY(machine.configuration().contains(s2));
}
+void tst_QStateMachine::parallelRootState()
+{
+ QStateMachine machine;
+ QState *root = machine.rootState();
+ QCOMPARE(root->childMode(), QState::ExclusiveStates);
+ root->setChildMode(QState::ParallelStates);
+ QCOMPARE(root->childMode(), QState::ParallelStates);
+
+ QState *s1 = new QState(root);
+ QFinalState *s1_f = new QFinalState(s1);
+ s1->setInitialState(s1_f);
+ QState *s2 = new QState(root);
+ QFinalState *s2_f = new QFinalState(s2);
+ s2->setInitialState(s2_f);
+
+ QSignalSpy startedSpy(&machine, SIGNAL(started()));
+ QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start.");
+ machine.start();
+ QCoreApplication::processEvents();
+ QEXPECT_FAIL("", "parallel root state is not supported (task 256587)", Continue);
+ QCOMPARE(startedSpy.count(), 1);
+}
+
void tst_QStateMachine::allSourceToTargetConfigurations()
{
QStateMachine machine;
@@ -1957,6 +1981,31 @@ void tst_QStateMachine::signalTransitions()
QCOMPARE(machine.configuration().size(), 1);
QVERIFY(machine.configuration().contains(s3));
}
+ // signature normalization
+ {
+ QStateMachine machine;
+ SignalEmitter emitter;
+ QState *s0 = new QState(machine.rootState());
+ QFinalState *s1 = new QFinalState(machine.rootState());
+ QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL( signalWithNoArg( ) ), s1);
+ QVERIFY(t0 != 0);
+ QCOMPARE(t0->signal(), QByteArray(SIGNAL( signalWithNoArg( ) )));
+
+ QSignalTransition *t1 = s0->addTransition(&emitter, SIGNAL( signalWithStringArg( const QString & ) ), s1);
+ QVERIFY(t1 != 0);
+ QCOMPARE(t1->signal(), QByteArray(SIGNAL( signalWithStringArg( const QString & ) )));
+
+ QSignalSpy startedSpy(&machine, SIGNAL(started()));
+ QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
+ machine.setInitialState(s0);
+ machine.start();
+ QTRY_COMPARE(startedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ emitter.emitSignalWithNoArg();
+
+ QTRY_COMPARE(finishedSpy.count(), 1);
+ }
}
void tst_QStateMachine::eventTransitions()
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index e8cb089..f11aff9 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -75,7 +75,11 @@ private slots:
void stylePropagation() const;
void matrixForElement() const;
void gradientStops() const;
+ void gradientRefs();
void fillRule();
+ void opacity();
+ void paths();
+ void displayMode();
#ifndef QT_NO_COMPRESS
void testGzLoading();
@@ -331,7 +335,7 @@ void tst_QSvgRenderer::nestedQXmlStreamReader() const
QCOMPARE(reader.readNext(), QXmlStreamReader::StartDocument);
QCOMPARE(reader.readNext(), QXmlStreamReader::StartElement);
QCOMPARE(reader.name().toString(), QLatin1String("bar"));
-
+
QPicture picture;
QPainter painter(&picture);
QSvgRenderer renderer(&reader);
@@ -533,7 +537,10 @@ void tst_QSvgRenderer::gradientStops() const
QCOMPARE(image, refImage);
}
+}
+void tst_QSvgRenderer::gradientRefs()
+{
const char *svgs[] = {
"<svg>"
"<defs>"
@@ -565,6 +572,17 @@ void tst_QSvgRenderer::gradientStops() const
"</linearGradient>"
"</defs>"
"<rect fill=\"url(#gradient)\" height=\"8\" width=\"256\" x=\"0\" y=\"0\"/>"
+ "</svg>",
+ "<svg>"
+ "<rect fill=\"url(#gradient)\" height=\"8\" width=\"256\" x=\"0\" y=\"0\"/>"
+ "<defs>"
+ "<linearGradient id=\"gradient0\">"
+ "<stop offset=\"0\" stop-color=\"red\" stop-opacity=\"0\"/>"
+ "<stop offset=\"1\" stop-color=\"blue\"/>"
+ "</linearGradient>"
+ "<linearGradient id=\"gradient\" xlink:href=\"#gradient0\">"
+ "</linearGradient>"
+ "</defs>"
"</svg>"
};
for (int i = 0 ; i < sizeof(svgs) / sizeof(svgs[0]) ; ++i)
@@ -589,6 +607,7 @@ void tst_QSvgRenderer::gradientStops() const
}
}
+
#ifndef QT_NO_COMPRESS
void tst_QSvgRenderer::testGzLoading()
{
@@ -653,22 +672,257 @@ void tst_QSvgRenderer::testGzHelper()
void tst_QSvgRenderer::fillRule()
{
- QByteArray data(
+ static const char *svgs[] = {
+ // Paths
+ // Default fill-rule (nonzero)
"<svg>"
- "<rect x=\"0\" y=\"0\" height=\"300\" width=\"400\" fill=\"blue\" />"
- "<path d=\"M100 200 L300 200 L300 100 L100 100 M100 200 L300 200 L300 100 L100 100 Z\" fill=\"red\" stroke=\"black\" />"
- "</svg>");
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <path d=\"M10 0 L30 0 L30 30 L0 30 L0 10 L20 10 L20 20 L10 20 Z\" fill=\"red\" />"
+ "</svg>",
+ // nonzero
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <path d=\"M10 0 L30 0 L30 30 L0 30 L0 10 L20 10 L20 20 L10 20 Z\" fill=\"red\" fill-rule=\"nonzero\" />"
+ "</svg>",
+ // evenodd
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <path d=\"M10 0 L30 0 L30 30 L0 30 L0 10 L20 10 L20 20 L10 20 Z\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>",
- QSvgRenderer renderer(data);
+ // Polygons
+ // Default fill-rule (nonzero)
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <polygon points=\"10 0 30 0 30 30 0 30 0 10 20 10 20 20 10 20\" fill=\"red\" />"
+ "</svg>",
+ // nonzero
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <polygon points=\"10 0 30 0 30 30 0 30 0 10 20 10 20 20 10 20\" fill=\"red\" fill-rule=\"nonzero\" />"
+ "</svg>",
+ // evenodd
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"30\" width=\"30\" fill=\"blue\" />"
+ " <polygon points=\"10 0 30 0 30 30 0 30 0 10 20 10 20 20 10 20\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>"
+ };
- QImage image(128, 128, QImage::Format_ARGB32_Premultiplied);
- image.fill(0);
+ const int COUNT = sizeof(svgs) / sizeof(svgs[0]);
+ QImage refImageNonZero(30, 30, QImage::Format_ARGB32_Premultiplied);
+ QImage refImageEvenOdd(30, 30, QImage::Format_ARGB32_Premultiplied);
+ refImageNonZero.fill(0xffff0000);
+ refImageEvenOdd.fill(0xffff0000);
+ QPainter p;
+ p.begin(&refImageNonZero);
+ p.fillRect(QRectF(0, 0, 10, 10), Qt::blue);
+ p.end();
+ p.begin(&refImageEvenOdd);
+ p.fillRect(QRectF(0, 0, 10, 10), Qt::blue);
+ p.fillRect(QRectF(10, 10, 10, 10), Qt::blue);
+ p.end();
+
+ for (int i = 0; i < COUNT; ++i) {
+ QByteArray data(svgs[i]);
+ QSvgRenderer renderer(data);
+ QImage image(30, 30, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ p.begin(&image);
+ renderer.render(&p);
+ p.end();
+ QCOMPARE(image, i % 3 == 2 ? refImageEvenOdd : refImageNonZero);
+ }
+}
+static void opacity_drawSvgAndVerify(const QByteArray &data)
+{
+ QSvgRenderer renderer(data);
+ QVERIFY(renderer.isValid());
+ QImage image(10, 10, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0xffff00ff);
QPainter painter(&image);
renderer.render(&painter);
painter.end();
+ QCOMPARE(image.pixel(5, 5), 0xff7f7f7f);
+}
+
+void tst_QSvgRenderer::opacity()
+{
+ static const char *opacities[] = {"-1,4641", "0", "0.5", "1", "1.337"};
+ static const char *firstColors[] = {"#7f7f7f", "#7f7f7f", "#402051", "blue", "#123456"};
+ static const char *secondColors[] = {"red", "#bad", "#bedead", "#7f7f7f", "#7f7f7f"};
+
+ // Fill-opacity
+ for (int i = 0; i < 5; ++i) {
+ QByteArray data("<svg><rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"");
+ data.append(firstColors[i]);
+ data.append("\"/><rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"");
+ data.append(secondColors[i]);
+ data.append("\" fill-opacity=\"");
+ data.append(opacities[i]);
+ data.append("\"/></svg>");
+ opacity_drawSvgAndVerify(data);
+ }
+ // Stroke-opacity
+ for (int i = 0; i < 5; ++i) {
+ QByteArray data("<svg viewBox=\"0 0 10 10\"><polyline points=\"0 5 10 5\" fill=\"none\" stroke=\"");
+ data.append(firstColors[i]);
+ data.append("\" stroke-width=\"10\"/><line x1=\"5\" y1=\"0\" x2=\"5\" y2=\"10\" fill=\"none\" stroke=\"");
+ data.append(secondColors[i]);
+ data.append("\" stroke-width=\"10\" stroke-opacity=\"");
+ data.append(opacities[i]);
+ data.append("\"/></svg>");
+ opacity_drawSvgAndVerify(data);
+ }
+ // As gradients:
+ // Fill-opacity
+ for (int i = 0; i < 5; ++i) {
+ QByteArray data("<svg><defs><linearGradient id=\"gradient\"><stop offset=\"0\" stop-color=\"");
+ data.append(secondColors[i]);
+ data.append("\"/><stop offset=\"1\" stop-color=\"");
+ data.append(secondColors[i]);
+ data.append("\"/></linearGradient></defs><rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"");
+ data.append(firstColors[i]);
+ data.append("\"/><rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"url(#gradient)\" fill-opacity=\"");
+ data.append(opacities[i]);
+ data.append("\"/></svg>");
+ opacity_drawSvgAndVerify(data);
+ }
+ // When support for gradients on strokes has been implemented, add the code below.
+ /*
+ // Stroke-opacity
+ for (int i = 0; i < 5; ++i) {
+ QByteArray data("<svg viewBox=\"0 0 10 10\"><defs><linearGradient id=\"grad\"><stop offset=\"0\" stop-color=\"");
+ data.append(secondColors[i]);
+ data.append("\"/><stop offset=\"1\" stop-color=\"");
+ data.append(secondColors[i]);
+ data.append("\"/></linearGradient></defs><polyline points=\"0 5 10 5\" fill=\"none\" stroke=\"");
+ data.append(firstColors[i]);
+ data.append("\" stroke-width=\"10\" /><line x1=\"5\" y1=\"0\" x2=\"5\" y2=\"10\" fill=\"none\" stroke=\"url(#grad)\" stroke-width=\"10\" stroke-opacity=\"");
+ data.append(opacities[i]);
+ data.append("\" /></svg>");
+ opacity_drawSvgAndVerify(data);
+ }
+ */
+}
+
+void tst_QSvgRenderer::paths()
+{
+ static const char *svgs[] = {
+ // Absolute coordinates, explicit commands.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\"M50 0 V50 H0 Q0 25 25 25 T50 0 C25 0 50 50 25 50 S25 0 0 0 Z\" fill=\"red\" fill-rule=\"evenodd\"/>"
+ "</svg>",
+ // Absolute coordinates, implicit commands.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\"M50 0 50 50 0 50 Q0 25 25 25 Q50 25 50 0 C25 0 50 50 25 50 C0 50 25 0 0 0 Z\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>",
+ // Relative coordinates, explicit commands.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\"m50 0 v50 h-50 q0 -25 25 -25 t25 -25 c-25 0 0 50 -25 50 s0 -50 -25 -50 z\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>",
+ // Relative coordinates, implicit commands.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\"m50 0 0 50 -50 0 q0 -25 25 -25 25 0 25 -25 c-25 0 0 50 -25 50 -25 0 0 -50 -25 -50 z\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>",
+ // Absolute coordinates, explicit commands, minimal whitespace.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\"m50 0v50h-50q0-25 25-25t25-25c-25 0 0 50-25 50s0-50-25-50z\" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>",
+ // Absolute coordinates, explicit commands, extra whitespace.
+ "<svg>"
+ " <rect x=\"0\" y=\"0\" height=\"50\" width=\"50\" fill=\"blue\" />"
+ " <path d=\" M 50 0 V 50 H 0 Q 0 25 25 25 T 50 0 C 25 0 50 50 25 50 S 25 0 0 0 Z \" fill=\"red\" fill-rule=\"evenodd\" />"
+ "</svg>"
+ };
+
+ const int COUNT = sizeof(svgs) / sizeof(svgs[0]);
+ QImage images[COUNT];
+ QPainter p;
+
+ for (int i = 0; i < COUNT; ++i) {
+ QByteArray data(svgs[i]);
+ QSvgRenderer renderer(data);
+ QVERIFY(renderer.isValid());
+ images[i] = QImage(50, 50, QImage::Format_ARGB32_Premultiplied);
+ images[i].fill(0);
+ p.begin(&images[i]);
+ renderer.render(&p);
+ p.end();
+ if (i != 0) {
+ QCOMPARE(images[i], images[0]);
+ }
+ }
+}
+
+void tst_QSvgRenderer::displayMode()
+{
+ static const char *svgs[] = {
+ // All visible.
+ "<svg>"
+ " <g>"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" />"
+ " </g>"
+ "</svg>",
+ // Don't display svg element.
+ "<svg display=\"none\">"
+ " <g>"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" />"
+ " </g>"
+ "</svg>",
+ // Don't display g element.
+ "<svg>"
+ " <g display=\"none\">"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" />"
+ " </g>"
+ "</svg>",
+ // Don't display first rect element.
+ "<svg>"
+ " <g>"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" display=\"none\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" />"
+ " </g>"
+ "</svg>",
+ // Don't display second rect element.
+ "<svg>"
+ " <g>"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" display=\"none\" />"
+ " </g>"
+ "</svg>",
+ // Don't display svg element, but set display mode to "inline" for other elements.
+ "<svg display=\"none\">"
+ " <g display=\"inline\">"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"red\" display=\"inline\" />"
+ " <rect x=\"0\" y=\"0\" height=\"10\" width=\"10\" fill=\"blue\" display=\"inline\" />"
+ " </g>"
+ "</svg>"
+ };
+
+ QRgb expectedColors[] = {0xff0000ff, 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00};
+
+ const int COUNT = sizeof(svgs) / sizeof(svgs[0]);
+ QPainter p;
- QCOMPARE(image.pixel(64, 64), QColor(Qt::red).rgba());
+ for (int i = 0; i < COUNT; ++i) {
+ QByteArray data(svgs[i]);
+ QSvgRenderer renderer(data);
+ QVERIFY(renderer.isValid());
+ QImage image(10, 10, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0xff00ff00);
+ p.begin(&image);
+ renderer.render(&p);
+ p.end();
+ QCOMPARE(image.pixel(5, 5), expectedColors[i]);
+ }
}
QTEST_MAIN(tst_QSvgRenderer)
diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf
index 6e0253a..d427a86 100644
--- a/tools/qdoc3/test/qt-build-docs.qdocconf
+++ b/tools/qdoc3/test/qt-build-docs.qdocconf
@@ -29,7 +29,6 @@ qhp.Qt.indexRoot =
# See also extraimages.HTML
qhp.Qt.extraFiles = classic.css \
images/qt-logo.png \
- images/trolltech-logo \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \
diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf
index e1ce8d3..9c43b4f 100644
--- a/tools/qdoc3/test/qt.qdocconf
+++ b/tools/qdoc3/test/qt.qdocconf
@@ -31,7 +31,6 @@ qhp.Qt.indexRoot =
# See also extraimages.HTML
qhp.Qt.extraFiles = classic.css \
images/qt-logo.png \
- images/trolltech-logo \
images/taskmenuextension-example.png \
images/coloreditorfactoryimage.png \
images/dynamiclayouts-example.png \