summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qfile.cpp46
-rw-r--r--src/corelib/io/qfile_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_p.h4
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp40
-rw-r--r--src/corelib/io/qiodevice.cpp163
-rw-r--r--src/corelib/io/qiodevice_p.h127
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp114
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h7
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h67
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp14
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp51
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h9
-rw-r--r--src/multimedia/audio/qaudioinput_mac_p.cpp4
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp157
14 files changed, 682 insertions, 123 deletions
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index aa1c7d9..50e9a8f 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -90,7 +90,8 @@ QFile::DecoderFn QFilePrivate::decoder = locale_decode;
QFilePrivate::QFilePrivate()
: fileEngine(0), lastWasWrite(false),
- writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError)
+ writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
+ cachedSize(0)
{
}
@@ -1257,8 +1258,10 @@ QFile::resize(qint64 sz)
seek(sz);
if(d->fileEngine->setSize(sz)) {
unsetError();
+ d->cachedSize = sz;
return true;
}
+ d->cachedSize = 0;
d->setError(QFile::ResizeError, d->fileEngine->errorString());
return false;
}
@@ -1420,7 +1423,8 @@ qint64 QFile::size() const
Q_D(const QFile);
if (!d->ensureFlushed())
return 0;
- return fileEngine()->size();
+ d->cachedSize = fileEngine()->size();
+ return d->cachedSize;
}
/*!
@@ -1446,16 +1450,16 @@ bool QFile::atEnd() const
{
Q_D(const QFile);
+ // If there's buffered data left, we're not at the end.
+ if (!d->buffer.isEmpty())
+ return false;
+
if (!isOpen())
return true;
if (!d->ensureFlushed())
return false;
- // If there's buffered data left, we're not at the end.
- if (!d->buffer.isEmpty())
- return false;
-
// If the file engine knows best, say what it says.
if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
// Check if the file engine supports AtEndExtension, and if it does,
@@ -1463,6 +1467,11 @@ bool QFile::atEnd() const
return d->fileEngine->atEnd();
}
+ // if it looks like we are at the end, or if size is not cached,
+ // fall through to bytesAvailable() to make sure.
+ if (pos() < d->cachedSize)
+ return false;
+
// Fall back to checking how much is available (will stat files).
return bytesAvailable() == 0;
}
@@ -1502,12 +1511,21 @@ qint64 QFile::readLineData(char *data, qint64 maxlen)
if (!d->ensureFlushed())
return -1;
- if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension))
- return d->fileEngine->readLine(data, maxlen);
+ qint64 read;
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
+ read = d->fileEngine->readLine(data, maxlen);
+ } else {
+ // Fall back to QIODevice's readLine implementation if the engine
+ // cannot do it faster.
+ read = QIODevice::readLineData(data, maxlen);
+ }
+
+ if (read < maxlen) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
- // Fall back to QIODevice's readLine implementation if the engine
- // cannot do it faster.
- return QIODevice::readLineData(data, maxlen);
+ return read;
}
/*!
@@ -1528,6 +1546,12 @@ qint64 QFile::readData(char *data, qint64 len)
err = QFile::ReadError;
d->setError(err, d->fileEngine->errorString());
}
+
+ if (read < len) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
return read;
}
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index f8f5f5c..cf76c09 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -84,6 +84,8 @@ protected:
void setError(QFile::FileError err, const QString &errorString);
void setError(QFile::FileError err, int errNum);
+ mutable qint64 cachedSize;
+
private:
static QFile::EncoderFn encoder;
static QFile::DecoderFn decoder;
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 0f63eb8..e50777b 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -151,6 +151,10 @@ public:
static bool uncListSharesOnServer(const QString &server, QStringList *list);
#endif
+#ifdef Q_OS_SYMBIAN
+ void setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString);
+#endif
+
protected:
QFSFileEnginePrivate();
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 1331f54..33e00f6 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -81,6 +81,40 @@ static bool isRelativePathSymbian(const QString& fileName)
&& ((fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':'))
|| (fileName.at(0) == QLatin1Char('/') && fileName.at(1) == QLatin1Char('/')))));
}
+
+/*!
+ \internal
+ convert symbian error code to the one suitable for setError.
+ example usage: setSymbianError(err, QFile::CopyError, QLatin1String("copy error"))
+*/
+void QFSFileEnginePrivate::setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString)
+{
+ Q_Q(QFSFileEngine);
+ switch (symbianError) {
+ case KErrNone:
+ q->setError(QFile::NoError, QLatin1String(""));
+ break;
+ case KErrAccessDenied:
+ q->setError(QFile::PermissionsError, QLatin1String("access denied"));
+ break;
+ case KErrPermissionDenied:
+ q->setError(QFile::PermissionsError, QLatin1String("permission denied"));
+ break;
+ case KErrAbort:
+ q->setError(QFile::AbortError, QLatin1String("aborted"));
+ break;
+ case KErrCancel:
+ q->setError(QFile::AbortError, QLatin1String("cancelled"));
+ break;
+ case KErrTimedOut:
+ q->setError(QFile::TimeOutError, QLatin1String("timed out"));
+ break;
+ default:
+ q->setError(defaultError, defaultString);
+ break;
+ }
+}
+
#endif
/*!
@@ -427,8 +461,10 @@ bool QFSFileEngine::copy(const QString &newName)
}
) // End TRAP
delete fm;
- // ### Add error reporting on failure
- return (err == KErrNone);
+ if (err == KErrNone)
+ return true;
+ d->setSymbianError(err, QFile::CopyError, QLatin1String("copy error"));
+ return false;
#else
Q_UNUSED(newName);
// ### Add copy code for Unix here
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index c93f0c3..f83c142 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -84,10 +84,6 @@ void debugBinaryString(const char *data, qint64 maxlen)
}
#endif
-#ifndef QIODEVICE_BUFFERSIZE
-#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
-#endif
-
#define Q_VOID
#define CHECK_MAXLEN(function, returnType) \
@@ -123,7 +119,9 @@ void debugBinaryString(const char *data, qint64 maxlen)
QIODevicePrivate::QIODevicePrivate()
: openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE),
pos(0), devicePos(0)
+ , pPos(&pos), pDevicePos(&devicePos)
, baseReadLineDataCalled(false)
+ , firstRead(true)
, accessMode(Unset)
#ifdef QT_NO_QOBJECT
, q_ptr(0)
@@ -449,11 +447,15 @@ QIODevice::OpenMode QIODevice::openMode() const
*/
void QIODevice::setOpenMode(OpenMode openMode)
{
+ Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::setOpenMode(0x%x)\n", this, int(openMode));
#endif
- d_func()->openMode = openMode;
- d_func()->accessMode = QIODevicePrivate::Unset;
+ d->openMode = openMode;
+ d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
+ if (!isReadable())
+ d->buffer.clear();
}
/*!
@@ -537,6 +539,7 @@ bool QIODevice::open(OpenMode mode)
d->pos = (mode & Append) ? size() : qint64(0);
d->buffer.clear();
d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::open(0x%x)\n", this, quint32(mode));
#endif
@@ -566,6 +569,7 @@ void QIODevice::close()
d->errorString.clear();
d->pos = 0;
d->buffer.clear();
+ d->firstRead = true;
}
/*!
@@ -729,6 +733,12 @@ qint64 QIODevice::bytesToWrite() const
return qint64(0);
}
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
/*!
Reads at most \a maxSize bytes from the device into \a data, and
returns the number of bytes read. If an error occurs, such as when
@@ -745,21 +755,17 @@ qint64 QIODevice::bytesToWrite() const
qint64 QIODevice::read(char *data, qint64 maxSize)
{
Q_D(QIODevice);
- CHECK_READABLE(read, qint64(-1));
- CHECK_MAXLEN(read, qint64(-1));
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
#endif
- const bool sequential = d->isSequential();
// Short circuit for getChar()
if (maxSize == 1) {
int chint;
while ((chint = d->buffer.getChar()) != -1) {
- if (!sequential)
- ++d->pos;
+ ++(*d->pPos);
char c = char(uchar(chint));
if (c == '\r' && (d->openMode & Text))
@@ -773,61 +779,77 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
}
+ CHECK_MAXLEN(read, qint64(-1));
qint64 readSoFar = 0;
bool moreToRead = true;
do {
- int lastReadChunkSize = 0;
-
// Try reading from the buffer.
- if (!d->buffer.isEmpty()) {
- lastReadChunkSize = d->buffer.read(data + readSoFar, maxSize - readSoFar);
- readSoFar += lastReadChunkSize;
- if (!sequential)
- d->pos += lastReadChunkSize;
+ int lastReadChunkSize = d->buffer.read(data, maxSize);
+ *d->pPos += lastReadChunkSize;
+ readSoFar += lastReadChunkSize;
+ // fast exit when satisfied by buffer
+ if (lastReadChunkSize == maxSize && !(d->openMode & Text))
+ return readSoFar;
+
+ if (lastReadChunkSize > 0) {
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize,
int(readSoFar) - lastReadChunkSize);
#endif
- } else if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
- // In buffered mode, we try to fill up the QIODevice buffer before
- // we do anything else.
- int bytesToBuffer = qMax(maxSize - readSoFar, QIODEVICE_BUFFERSIZE);
- char *writePointer = d->buffer.reserve(bytesToBuffer);
-
- // Make sure the device is positioned correctly.
- if (d->pos != d->devicePos && !sequential && !seek(d->pos))
- return qint64(-1);
- qint64 readFromDevice = readData(writePointer, bytesToBuffer);
- d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
+ } else {
+ if (d->firstRead) {
+ // this is the first time the file has been read, check it's valid and set up pos pointers
+ // for fast pos updates.
+ CHECK_READABLE(read, qint64(-1));
+ d->firstRead = false;
+ if (d->isSequential()) {
+ d->pPos = &d->seqDumpPos;
+ d->pDevicePos = &d->seqDumpPos;
+ }
+ }
- if (readFromDevice > 0) {
- if (!sequential)
- d->devicePos += readFromDevice;
+ if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
+ // In buffered mode, we try to fill up the QIODevice buffer before
+ // we do anything else.
+ // buffer is empty at this point, try to fill it
+ int bytesToBuffer = QIODEVICE_BUFFERSIZE;
+ char *writePointer = d->buffer.reserve(bytesToBuffer);
+
+ // Make sure the device is positioned correctly.
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(writePointer, bytesToBuffer);
+ d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
+
+ if (readFromDevice > 0) {
+ *d->pDevicePos += readFromDevice;
#if defined QIODEVICE_DEBUG
- printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
+ printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
#endif
- if (readFromDevice < bytesToBuffer)
- d->buffer.truncate(int(readFromDevice));
- if (!d->buffer.isEmpty()) {
- lastReadChunkSize = d->buffer.read(data + readSoFar, maxSize - readSoFar);
- readSoFar += lastReadChunkSize;
- if (!sequential)
- d->pos += lastReadChunkSize;
+ if (!d->buffer.isEmpty()) {
+ lastReadChunkSize = d->buffer.read(data, maxSize);
+ readSoFar += lastReadChunkSize;
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
+ *d->pPos += lastReadChunkSize;
#if defined QIODEVICE_DEBUG
- printf("%p \treading %d bytes from buffer at position %d\n", this,
- lastReadChunkSize, int(readSoFar));
+ printf("%p \treading %d bytes from buffer at position %d\n", this,
+ lastReadChunkSize, int(readSoFar));
#endif
+ }
}
}
}
// If we need more, try reading from the device.
- if (readSoFar < maxSize) {
+ if (maxSize > 0) {
// Make sure the device is positioned correctly.
- if (d->pos != d->devicePos && !sequential && !seek(d->pos))
- return qint64(-1);
- qint64 readFromDevice = readData(data + readSoFar, maxSize - readSoFar);
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(data, maxSize);
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar));
#endif
@@ -835,27 +857,21 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
// error and we haven't read anything: return immediately
return -1;
}
- if (readFromDevice <= 0) {
- moreToRead = false;
- } else {
- // see if we read as much data as we asked for
- if (readFromDevice < maxSize - readSoFar)
- moreToRead = false;
-
+ if (readFromDevice > 0) {
lastReadChunkSize += int(readFromDevice);
readSoFar += readFromDevice;
- if (!sequential) {
- d->pos += readFromDevice;
- d->devicePos += readFromDevice;
- }
+ data += readFromDevice;
+ maxSize -= readFromDevice;
+ *d->pPos += readFromDevice;
+ *d->pDevicePos += readFromDevice;
}
- } else {
- moreToRead = false;
}
+ // Best attempt has been made to read data, don't try again except for text mode adjustment below
+ moreToRead = false;
if (readSoFar && d->openMode & Text) {
- char *readPtr = data + readSoFar - lastReadChunkSize;
- const char *endPtr = data + readSoFar;
+ char *readPtr = data - lastReadChunkSize;
+ const char *endPtr = data;
if (readPtr < endPtr) {
// optimization to avoid initial self-assignment
@@ -870,8 +886,11 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
char ch = *readPtr++;
if (ch != '\r')
*writePtr++ = ch;
- else
+ else {
--readSoFar;
+ --data;
+ ++maxSize;
+ }
}
// Make sure we get more data if there is room for more. This
@@ -885,11 +904,15 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
#if defined QIODEVICE_DEBUG
printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this,
int(readSoFar), int(d->pos), d->buffer.size());
- debugBinaryString(data, readSoFar);
+ debugBinaryString(data - readSoFar, readSoFar);
#endif
return readSoFar;
}
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
/*!
\overload
@@ -997,6 +1020,12 @@ QByteArray QIODevice::readAll()
return result;
}
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
/*!
This function reads a line of ASCII characters from the device, up
to a maximum of \a maxSize - 1 bytes, stores the characters in \a
@@ -1229,6 +1258,10 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize)
return readSoFar;
}
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
/*!
Returns true if a complete line of data can be read from the device;
otherwise returns false.
@@ -1416,9 +1449,7 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
bool QIODevice::getChar(char *c)
{
- Q_D(QIODevice);
- CHECK_READABLE(getChar, false);
-
+ // readability checked in read()
char ch;
return (1 == read(c ? c : &ch, 1));
}
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index cc4a237..94dadca 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -64,6 +64,126 @@
QT_BEGIN_NAMESPACE
+#ifndef QIODEVICE_BUFFERSIZE
+#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
+#endif
+
+// This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar()
+class QIODevicePrivateLinearBuffer
+{
+public:
+ QIODevicePrivateLinearBuffer(int) : len(0), first(0), buf(0), capacity(0) {
+ }
+ ~QIODevicePrivateLinearBuffer() {
+ delete [] buf;
+ }
+ void clear() {
+ first = buf;
+ len = 0;
+ }
+ int size() const {
+ return len;
+ }
+ bool isEmpty() const {
+ return len == 0;
+ }
+ void skip(int n) {
+ if (n >= len) {
+ clear();
+ } else {
+ len -= n;
+ first += n;
+ }
+ }
+ int getChar() {
+ if (len == 0)
+ return -1;
+ int ch = uchar(*first);
+ len--;
+ first++;
+ return ch;
+ }
+ int read(char* target, int size) {
+ int r = qMin(size, len);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return r;
+ }
+ char* reserve(int size) {
+ makeSpace(size + len, freeSpaceAtEnd);
+ char* writePtr = first + len;
+ len += size;
+ return writePtr;
+ }
+ void chop(int size) {
+ if (size >= len) {
+ clear();
+ } else {
+ len -= size;
+ }
+ }
+ QByteArray readAll() {
+ char* f = first;
+ int l = len;
+ clear();
+ return QByteArray(f, l);
+ }
+ int readLine(char* target, int size) {
+ int r = qMin(size, len);
+ char* eol = static_cast<char*>(memchr(first, '\n', r));
+ if (eol)
+ r = 1+(eol-first);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return int(r);
+ }
+ bool canReadLine() const {
+ return memchr(first, '\n', len);
+ }
+ void ungetChar(char c) {
+ if (first == buf) {
+ // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
+ makeSpace(len+1, freeSpaceAtStart);
+ }
+ first--;
+ len++;
+ *first = c;
+ }
+
+private:
+ enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd};
+ void makeSpace(size_t required, FreeSpacePos where) {
+ size_t newCapacity = qMax(capacity, size_t(QIODEVICE_BUFFERSIZE));
+ while (newCapacity < required)
+ newCapacity *= 2;
+ int moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - len;
+ if (newCapacity > capacity) {
+ // allocate more space
+ char* newBuf = new char[newCapacity];
+ memmove(newBuf + moveOffset, first, len);
+ delete [] buf;
+ buf = newBuf;
+ capacity = newCapacity;
+ } else {
+ // shift any existing data to make space
+ memmove(buf + moveOffset, first, len);
+ }
+ first = buf + moveOffset;
+ }
+
+private:
+ // length of the unread data
+ int len;
+ // start of the unread data
+ char* first;
+ // the allocated buffer
+ char* buf;
+ // allocated buffer size
+ size_t capacity;
+};
+
class Q_CORE_EXPORT QIODevicePrivate
#ifndef QT_NO_QOBJECT
: public QObjectPrivate
@@ -78,10 +198,15 @@ public:
QIODevice::OpenMode openMode;
QString errorString;
- QRingBuffer buffer;
+ QIODevicePrivateLinearBuffer buffer;
qint64 pos;
qint64 devicePos;
+ // these three are for fast position updates during read, avoiding isSequential test
+ qint64 seqDumpPos;
+ qint64 *pPos;
+ qint64 *pDevicePos;
bool baseReadLineDataCalled;
+ bool firstRead;
virtual bool putCharHelper(char c);
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index f3c90ca..f110a5c 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1130,6 +1130,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
+ // Resolve depth.
+ invalidateDepthRecursively();
+
if ((parent = newParent)) {
if (parent->d_func()->scene && parent->d_func()->scene != scene) {
// Move this item to its new parent's scene
@@ -1180,8 +1183,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
- // Resolve depth.
- invalidateDepthRecursively();
dirtySceneTransform = 1;
// Restore the sub focus chain.
@@ -2176,8 +2177,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- if (scene)
+ if (scene) {
+#ifndef QT_NO_GRAPHICSEFFECT
+ invalidateParentGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
@@ -5219,6 +5224,8 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
needSortChildren = 1; // ### maybe 0
child->d_ptr->siblingIndex = children.size();
children.append(child);
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -5241,6 +5248,8 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
// the child is not guaranteed to be at the index after the list is sorted.
// (see ensureSortedChildren()).
child->d_ptr->siblingIndex = -1;
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -7448,6 +7457,88 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
}
}
+void QGraphicsItemPrivate::append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
+{
+ QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+}
+
+/*!
+ Returns a list of this item's children.
+
+ The items are sorted by stacking order. This takes into account both the
+ items' insertion order and their Z-values.
+
+*/
+QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
+{
+ Q_Q(QGraphicsItem);
+ if (isObject) {
+ QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
+ return QDeclarativeListProperty<QGraphicsObject>(that, &children, QGraphicsItemPrivate::append);
+ } else {
+ //QGraphicsItem is not supported for this property
+ return QDeclarativeListProperty<QGraphicsObject>();
+ }
+}
+
+/*!
+ \internal
+ Returns the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::width() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setWidth(qreal w)
+{
+ Q_UNUSED(w);
+}
+
+/*!
+ \internal
+ Reset the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetWidth()
+{
+}
+
+/*!
+ \internal
+ Returns the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::height() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setHeight(qreal h)
+{
+ Q_UNUSED(h);
+}
+
+/*!
+ \internal
+ Reset the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetHeight()
+{
+}
+
/*!
\property QGraphicsObject::parent
\brief the parent of the item
@@ -7634,6 +7725,23 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
\sa scale, rotation, QGraphicsItem::transformOriginPoint()
*/
+/*!
+ \fn void QGraphicsObject::widthChanged()
+ \internal
+*/
+
+/*!
+ \fn void QGraphicsObject::heightChanged()
+ \internal
+*/
+
+/*!
+
+ \fn QGraphicsObject::childrenChanged()
+
+ This signal gets emitted whenever the children list changes
+ \internal
+*/
/*!
\class QAbstractGraphicsShapeItem
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index d72833b..5023f60 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -547,6 +547,10 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+ Q_CLASSINFO("DefaultProperty", "children")
Q_INTERFACES(QGraphicsItem)
public:
QGraphicsObject(QGraphicsItem *parent = 0);
@@ -571,6 +575,9 @@ Q_SIGNALS:
void zChanged();
void rotationChanged();
void scaleChanged();
+ void childrenChanged();
+ void widthChanged();
+ void heightChanged();
protected:
QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index ea04e0b..669ae1b 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -71,6 +71,62 @@ QT_BEGIN_NAMESPACE
class QGraphicsItemPrivate;
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
+template<typename T>
+struct QDeclarativeListProperty {
+ typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
+ typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
+ typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
+ typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
+
+ QDeclarativeListProperty()
+ : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, QList<T *> &list)
+ : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
+ clear(qlist_clear), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
+ ClearFunction r = 0)
+ : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+
+ bool operator==(const QDeclarativeListProperty &o) const {
+ return object == o.object &&
+ data == o.data &&
+ append == o.append &&
+ count == o.count &&
+ at == o.at &&
+ clear == o.clear;
+ }
+
+ QObject *object;
+ void *data;
+
+ AppendFunction append;
+
+ CountFunction count;
+ AtFunction at;
+
+ ClearFunction clear;
+
+ void *dummy1;
+ void *dummy2;
+
+private:
+ static void qlist_append(QDeclarativeListProperty *p, T *v) {
+ ((QList<T *> *)p->data)->append(v);
+ }
+ static int qlist_count(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->count();
+ }
+ static T *qlist_at(QDeclarativeListProperty *p, int idx) {
+ return ((QList<T *> *)p->data)->at(idx);
+ }
+ static void qlist_clear(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->clear();
+ }
+};
+#endif
+
class QGraphicsItemCache
{
public:
@@ -237,6 +293,7 @@ public:
void resolveDepth();
void addChild(QGraphicsItem *child);
void removeChild(QGraphicsItem *child);
+ QDeclarativeListProperty<QGraphicsObject> childrenList();
void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
const QVariant *thisPointerVariant);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
@@ -423,11 +480,21 @@ public:
inline QTransform transformToParent() const;
inline void ensureSortedChildren();
+ static void append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
void ensureSequentialSiblingIndex();
inline void sendScenePosChange();
virtual void siblingOrderChange();
+ // Private Properties
+ virtual qreal width() const;
+ virtual void setWidth(qreal);
+ virtual void resetWidth();
+
+ virtual qreal height() const;
+ virtual void setHeight(qreal);
+ virtual void resetHeight();
+
QRectF childrenBoundingRect;
QRectF needsRepaint;
QMap<QWidget *, QRect> paintedViewBoundingRects;
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index f42fe4f..a091347 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -324,6 +324,14 @@ void QGraphicsWidget::resize(const QSizeF &size)
*/
/*!
+
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry of the item changes
+ \internal
+*/
+
+/*!
\property QGraphicsWidget::geometry
\brief the geometry of the widget
@@ -391,6 +399,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
QGraphicsSceneResizeEvent re;
re.setOldSize(oldSize);
re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
QApplication::sendEvent(this, &re);
}
}
@@ -2322,5 +2334,7 @@ void QGraphicsWidget::dumpFocusChain()
#endif
QT_END_NAMESPACE
+
+#include "moc_qgraphicswidget.cpp"
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 1835c74..6e397b6 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_GRAPHICSVIEW
#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
@@ -825,6 +826,56 @@ void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
}
}
+qreal QGraphicsWidgetPrivate::width() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().width();
+}
+
+void QGraphicsWidgetPrivate::setWidth(qreal w)
+{
+ if (qIsNaN(w))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().width() == w)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), w, height()));
+}
+
+void QGraphicsWidgetPrivate::resetWidth()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
+}
+
+qreal QGraphicsWidgetPrivate::height() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().height();
+}
+
+void QGraphicsWidgetPrivate::setHeight(qreal h)
+{
+ if (qIsNaN(h))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().height() == h)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), width(), h));
+}
+
+void QGraphicsWidgetPrivate::resetHeight()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 2c5b3bf..f34a755 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -130,6 +130,15 @@ public:
void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event);
bool hasDecoration() const;
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
// State
inline int attributeToBitIndex(Qt::WidgetAttribute att) const
{
diff --git a/src/multimedia/audio/qaudioinput_mac_p.cpp b/src/multimedia/audio/qaudioinput_mac_p.cpp
index 4b37b18..cb65f6e 100644
--- a/src/multimedia/audio/qaudioinput_mac_p.cpp
+++ b/src/multimedia/audio/qaudioinput_mac_p.cpp
@@ -670,8 +670,8 @@ bool QAudioInputPrivate::open()
}
// Allocate buffer
- periodSizeBytes = (numberOfFrames * streamFormat.mSampleRate / deviceFormat.mSampleRate) *
- streamFormat.mBytesPerFrame;
+ periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
+
if (internalBufferSize < periodSizeBytes * 2)
internalBufferSize = periodSizeBytes * 2;
else
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index e75c19d..f41a914 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -131,11 +131,10 @@ class QODBCDriverPrivate
public:
enum DefaultCase{Lower, Mixed, Upper, Sensitive};
QODBCDriverPrivate()
- : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false),
- isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false),
- isQuoteInitialized(false), quote(QLatin1Char('"'))
+ : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), isMySqlServer(false),
+ isMSSqlServer(false), isFreeTDSDriver(false), hasSQLFetchScroll(true),
+ hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"'))
{
- unicode = false;
}
SQLHANDLE hEnv;
@@ -146,6 +145,7 @@ public:
int disconnectCount;
bool isMySqlServer;
bool isMSSqlServer;
+ bool isFreeTDSDriver;
bool hasSQLFetchScroll;
bool hasMultiResultSets;
@@ -172,7 +172,10 @@ public:
QODBCPrivate(QODBCDriverPrivate *dpp)
: hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false)
{
- unicode = false;
+ unicode = dpp->unicode;
+ useSchema = dpp->useSchema;
+ disconnectCount = dpp->disconnectCount;
+ hasSQLFetchScroll = dpp->hasSQLFetchScroll;
}
inline void clearValues()
@@ -349,7 +352,9 @@ static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, const T* p, bool isSi
#endif
case SQL_CHAR:
case SQL_VARCHAR:
+#if (ODBCVER >= 0x0350)
case SQL_GUID:
+#endif
case SQL_LONGVARCHAR:
type = QVariant::String;
break;
@@ -374,44 +379,88 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
} else {
colSize++; // make sure there is room for more than the 0 termination
}
- r = SQLGetData(hStmt,
- column+1,
- SQL_C_TCHAR,
- NULL,
- 0,
- &lengthIndicator);
- if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
- colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
- QVarLengthArray<SQLTCHAR> buf(colSize);
- while (true) {
+ if(unicode) {
r = SQLGetData(hStmt,
column+1,
SQL_C_TCHAR,
- (SQLPOINTER)buf.data(),
- colSize*sizeof(SQLTCHAR),
+ NULL,
+ 0,
&lengthIndicator);
- if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
- if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
+ QVarLengthArray<SQLTCHAR> buf(colSize);
+ memset(buf.data(), 0, colSize*sizeof(SQLTCHAR));
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_TCHAR,
+ (SQLPOINTER)buf.data(),
+ colSize*sizeof(SQLTCHAR),
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR);
+ fieldVal += fromSQLTCHAR(buf, rSize);
+ if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
+ } else {
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
fieldVal.clear();
break;
}
- // if SQL_SUCCESS_WITH_INFO is returned, indicating that
- // more data can be fetched, the length indicator does NOT
- // contain the number of bytes returned - it contains the
- // total number of bytes that CAN be fetched
- // colSize-1: remove 0 termination when there is more data to fetch
- int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR);
- fieldVal += fromSQLTCHAR(buf, rSize);
- if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) {
- // workaround for Drivermanagers that don't return SQL_NO_DATA
+ }
+ } else {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ NULL,
+ 0,
+ &lengthIndicator);
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator + 1;
+ QVarLengthArray<SQLCHAR> buf(colSize);
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ (SQLPOINTER)buf.data(),
+ colSize,
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator;
+ fieldVal += QString::fromUtf8((const char *)buf.constData(), rSize);
+ if (lengthIndicator < (unsigned int)colSize) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
+ } else {
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
+ fieldVal.clear();
break;
}
- } else if (r == SQL_NO_DATA) {
- break;
- } else {
- qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
}
}
return fieldVal;
@@ -866,10 +915,6 @@ QODBCResult::QODBCResult(const QODBCDriver * db, QODBCDriverPrivate* p)
: QSqlResult(db)
{
d = new QODBCPrivate(p);
- d->unicode = p->unicode;
- d->useSchema = p->useSchema;
- d->disconnectCount = p->disconnectCount;
- d->hasSQLFetchScroll = p->hasSQLFetchScroll;
}
QODBCResult::~QODBCResult()
@@ -1846,6 +1891,7 @@ bool QODBCDriver::open(const QString & db,
SQLSMALLINT cb;
QVarLengthArray<SQLTCHAR> connOut(1024);
+ memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
r = SQLDriverConnect(d->hDbc,
NULL,
#ifdef UNICODE
@@ -1943,6 +1989,7 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1952,6 +1999,7 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1961,7 +2009,25 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
unicode = true;
+ return;
+ }
+ SQLHANDLE hStmt;
+ r = SQLAllocHandle(SQL_HANDLE_STMT,
+ hDbc,
+ &hStmt);
+
+ r = SQLExecDirect(hStmt, toSQLTCHAR(QLatin1String("select 'test'")).data(), SQL_NTS);
+ if(r == SQL_SUCCESS) {
+ r = SQLFetch(hStmt);
+ if(r == SQL_SUCCESS) {
+ QVarLengthArray<SQLWCHAR> buffer(10);
+ r = SQLGetData(hStmt, 1, SQL_C_WCHAR, buffer.data(), buffer.size() * sizeof(SQLWCHAR), NULL);
+ if(r == SQL_SUCCESS && fromSQLTCHAR(buffer) == QLatin1String("test")) {
+ unicode = true;
+ }
+ }
}
+ r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
bool QODBCDriverPrivate::checkDriver() const
@@ -2053,6 +2119,21 @@ void QODBCDriverPrivate::checkSqlServer()
isMySqlServer = serverType.contains(QLatin1String("mysql"), Qt::CaseInsensitive);
isMSSqlServer = serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive);
}
+ r = SQLGetInfo(hDbc,
+ SQL_DRIVER_NAME,
+ serverString.data(),
+ serverString.size() * sizeof(SQLTCHAR),
+ &t);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ QString serverType;
+#ifdef UNICODE
+ serverType = fromSQLTCHAR(serverString, t/sizeof(SQLTCHAR));
+#else
+ serverType = QString::fromUtf8((const char *)serverString.constData(), t);
+#endif
+ isFreeTDSDriver = serverType.contains(QLatin1String("tdsodbc"), Qt::CaseInsensitive);
+ unicode = isFreeTDSDriver == false;
+ }
}
void QODBCDriverPrivate::checkHasSQLFetchScroll()