From 83670dbf53203757a28b10837b66f46515e1328d Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 17 Jul 2009 13:11:51 +0200 Subject: Animations: animations with 0 duration would never be auto-deleted --- src/corelib/animation/qabstractanimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 75decf8..cf3e62d 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -620,8 +620,8 @@ void QAbstractAnimation::start(DeletionPolicy policy) Q_D(QAbstractAnimation); if (d->state == Running) return; - d->setState(Running); d->deleteWhenStopped = policy; + d->setState(Running); } /*! -- cgit v0.12 From 430f93c3649aacea5d9ccab047f036027f0622ea Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 13 Jul 2009 17:48:04 +0200 Subject: tst_qhttpnetworkconnection: Fixes --- .../qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index e116624..aa0705d 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -244,8 +244,8 @@ void tst_QHttpNetworkConnection::get() QByteArray ba; do { QCoreApplication::instance()->processEvents(); - if (reply->bytesAvailable()) - ba += reply->read(); + while (reply->bytesAvailable()) + ba += reply->readAny(); if (stopWatch.elapsed() >= 30000) break; } while (!reply->isFinished()); @@ -327,7 +327,8 @@ void tst_QHttpNetworkConnection::put() if (reply->isFinished()) { QByteArray ba; - ba += reply->read(); + while (reply->bytesAvailable()) + ba += reply->readAny(); } else if(finishedWithErrorCalled) { if(!succeed) { delete reply; @@ -417,8 +418,8 @@ void tst_QHttpNetworkConnection::post() QByteArray ba; do { QCoreApplication::instance()->processEvents(); - if (reply->bytesAvailable()) - ba += reply->read(); + while (reply->bytesAvailable()) + ba += reply->readAny(); if (stopWatch.elapsed() >= 30000) break; } while (!reply->isFinished()); @@ -616,8 +617,8 @@ void tst_QHttpNetworkConnection::compression() QByteArray ba; do { QCoreApplication::instance()->processEvents(); - if (reply->bytesAvailable()) - ba += reply->read(); + while (reply->bytesAvailable()) + ba += reply->readAny(); if (stopWatch.elapsed() >= 30000) break; } while (!reply->isFinished()); -- cgit v0.12 From 8ab072aff0527d3ef3e44cf1ceba7dca985a6f94 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 15 Jul 2009 12:40:53 +0200 Subject: QNetworkAccessManager: HTTP download performance improvements Better usage of move semantics with implicit sharing to avoid detaching (=malloc/memcpy). Also some other improvements. Download performance improvement is around 20% according to the httpDownloadPerformance autotest. Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytedata_p.h | 200 +++++++++++++++++++++ src/corelib/tools/tools.pri | 1 + src/network/access/qhttpnetworkconnection.cpp | 61 ++++--- src/network/access/qhttpnetworkconnection_p.h | 8 +- src/network/access/qhttpnetworkreply.cpp | 78 ++++---- src/network/access/qhttpnetworkreply_p.h | 12 +- src/network/access/qnetworkaccessbackend.cpp | 4 +- src/network/access/qnetworkaccessbackend_p.h | 2 +- src/network/access/qnetworkaccessdatabackend.cpp | 6 +- .../access/qnetworkaccessdebugpipebackend.cpp | 6 +- src/network/access/qnetworkaccessfilebackend.cpp | 6 +- src/network/access/qnetworkaccessftpbackend.cpp | 6 +- src/network/access/qnetworkaccesshttpbackend.cpp | 11 +- src/network/access/qnetworkreplyimpl.cpp | 40 +++-- src/network/access/qnetworkreplyimpl_p.h | 5 +- 15 files changed, 338 insertions(+), 108 deletions(-) create mode 100644 src/corelib/tools/qbytedata_p.h diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h new file mode 100644 index 0000000..e8a4ddd --- /dev/null +++ b/src/corelib/tools/qbytedata_p.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module 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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBYTEDATA_H +#define QBYTEDATA_H + +#include + + +// this class handles a list of QByteArrays. It is a variant of QRingBuffer +// that avoid malloc/realloc/memcpy. +class QByteDataBuffer +{ +private: + QList buffers; + qint64 bufferCompleteSize; +public: + QByteDataBuffer() : bufferCompleteSize(0) + { + } + + ~QByteDataBuffer() + { + clear(); + } + + inline void append(QByteDataBuffer& other) + { + if (other.isEmpty()) + return; + + buffers.append(other.buffers); + bufferCompleteSize += other.byteAmount(); + } + + + inline void append(QByteArray& bd) + { + if (bd.isEmpty()) + return; + + buffers.append(bd); + bufferCompleteSize += bd.size(); + } + + inline void prepend(QByteArray& bd) + { + if (bd.isEmpty()) + return; + + buffers.prepend(bd); + bufferCompleteSize += bd.size(); + } + + // return the first QByteData. User of this function has to qFree() its .data! + // preferably use this function to read data. + inline QByteArray read() + { + bufferCompleteSize -= buffers.first().size(); + return buffers.takeFirst(); + } + + // return everything. User of this function has to qFree() its .data! + // avoid to use this, it might malloc and memcpy. + inline QByteArray readAll() + { + return read(byteAmount()); + } + + // return amount. User of this function has to qFree() its .data! + // avoid to use this, it might malloc and memcpy. + inline QByteArray read(qint64 amount) + { + amount = qMin(byteAmount(), amount); + QByteArray byteData; + byteData.resize(amount); + read(byteData.data(), byteData.size()); + return byteData; + } + + // return amount bytes. User of this function has to qFree() its .data! + // avoid to use this, it will memcpy. + qint64 read(char* dst, qint64 amount) + { + amount = qMin(amount, byteAmount()); + qint64 originalAmount = amount; + char *writeDst = dst; + + while (amount > 0) { + QByteArray first = buffers.takeFirst(); + if (amount >= first.size()) { + // take it completely + bufferCompleteSize -= first.size(); + amount -= first.size(); + memcpy(writeDst, first.constData(), first.size()); + writeDst += first.size(); + first.clear(); + } else { + // take a part of it & it is the last one to take + bufferCompleteSize -= amount; + memcpy(writeDst, first.constData(), amount); + + qint64 newFirstSize = first.size() - amount; + QByteArray newFirstData; + newFirstData.resize(newFirstSize); + memcpy(newFirstData.data(), first.constData() + amount, newFirstSize); + buffers.prepend(newFirstData); + + amount = 0; + first.clear(); + } + } + + return originalAmount; + } + + inline char getChar() + { + char c; + read(&c, 1); + return c; + } + + inline void clear() + { + buffers.clear(); + bufferCompleteSize = 0; + } + + // The byte count of all QByteArrays + inline qint64 byteAmount() const + { + return bufferCompleteSize; + } + + // the number of QByteArrays + inline qint64 bufferCount() const + { + return buffers.length(); + } + + inline bool isEmpty() const + { + return byteAmount() == 0; + } + + inline qint64 sizeNextBlock() const + { + if(buffers.isEmpty()) + return 0; + else + return buffers.first().size(); + } + + inline QByteArray& operator[](int i) + { + return buffers[i]; + } +}; + + +#endif // QBYTEDATA_H diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index c93a065..08c94ac 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -5,6 +5,7 @@ HEADERS += \ tools/qbitarray.h \ tools/qbytearray.h \ tools/qbytearraymatcher.h \ + tools/qbytedata_p.h \ tools/qcache.h \ tools/qchar.h \ tools/qcontainerfwd.h \ diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index f1da244..afcdf17 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -175,26 +175,43 @@ bool QHttpNetworkConnectionPrivate::isSocketReading(QAbstractSocket *socket) con return (i != -1 && (channels[i].state & ReadingState)); } +void QHttpNetworkConnectionPrivate::appendUncompressedData(QHttpNetworkReply &reply, QByteArray &qba) +{ + reply.d_func()->responseData.append(qba); + + // clear the original! helps with implicit sharing and + // avoiding memcpy when the user is reading the data + qba.clear(); +} -void QHttpNetworkConnectionPrivate::appendUncompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) +void QHttpNetworkConnectionPrivate::appendUncompressedData(QHttpNetworkReply &reply, QByteDataBuffer &data) { - char *dst = reply.d_func()->responseData.reserve(fragment.size()); - qMemCopy(dst, fragment.constData(), fragment.size()); + reply.d_func()->responseData.append(data); + + // clear the original! helps with implicit sharing and + // avoiding memcpy when the user is reading the data + data.clear(); } -void QHttpNetworkConnectionPrivate::appendCompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) +void QHttpNetworkConnectionPrivate::appendCompressedData(QHttpNetworkReply &reply, QByteDataBuffer &data) { - reply.d_func()->compressedData.append(fragment); + // Work in progress: Later we will directly use a list of QByteArray or a QRingBuffer + // instead of one QByteArray. + for(int i = 0; i < data.bufferCount(); i++) { + QByteArray &byteData = data[i]; + reply.d_func()->compressedData.append(byteData.constData(), byteData.size()); + } + data.clear(); } qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailable(const QHttpNetworkReply &reply) const { - return reply.d_func()->responseData.size(); + return reply.d_func()->responseData.byteAmount(); } qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const { - return reply.d_func()->responseData.nextDataBlockSize(); + return reply.d_func()->responseData.sizeNextBlock(); } qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetworkReply &reply) const @@ -202,21 +219,6 @@ qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetwor return reply.d_func()->compressedData.size(); } -qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize) -{ - QRingBuffer *rb = &reply.d_func()->responseData; - if (maxSize == -1 || maxSize >= rb->size()) { - // read the whole data - data = rb->readAll(); - rb->clear(); - } else { - // read only the requested length - data.resize(maxSize); - rb->read(data.data(), maxSize); - } - return data.size(); -} - void QHttpNetworkConnectionPrivate::eraseData(QHttpNetworkReply *reply) { reply->d_func()->compressedData.clear(); @@ -556,6 +558,8 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork reply->d_func()->totalProgress += inflated.size(); appendUncompressedData(*reply, inflated); if (shouldEmitSignals(reply)) { + // important: At the point of this readyRead(), inflated must be cleared, + // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); // make sure that the reply is valid if (channels[i].reply != reply) @@ -672,18 +676,19 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN { // use the traditional slower reading (for compressed encoding, chunked encoding, // no content-length etc) - QBuffer fragment; - fragment.open(QIODevice::WriteOnly); - bytes = reply->d_func()->readBody(socket, &fragment); + QByteDataBuffer byteDatas; + bytes = reply->d_func()->readBody(socket, &byteDatas); if (bytes) { if (reply->d_func()->autoDecompress) - appendCompressedData(*reply, fragment.data()); + appendCompressedData(*reply, byteDatas); else - appendUncompressedData(*reply, fragment.data()); + appendUncompressedData(*reply, byteDatas); if (!reply->d_func()->autoDecompress) { - reply->d_func()->totalProgress += fragment.size(); + reply->d_func()->totalProgress += bytes; if (shouldEmitSignals(reply)) { + // important: At the point of this readyRead(), the byteDatas list must be empty, + // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); // make sure that the reply is valid if (channels[i].reply != reply) diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index a0813d4..842a2f4 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -79,6 +79,7 @@ QT_BEGIN_NAMESPACE class QHttpNetworkRequest; class QHttpNetworkReply; +class QByteArray; class QHttpNetworkConnectionPrivate; class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject @@ -255,15 +256,14 @@ public: bool pendingAuthSignal; // there is an incomplete authentication signal bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal - void appendUncompressedData(QHttpNetworkReply &reply, const QByteArray &fragment); - void appendCompressedData(QHttpNetworkReply &reply, const QByteArray &fragment); + void appendUncompressedData(QHttpNetworkReply &reply, QByteArray &qba); + void appendUncompressedData(QHttpNetworkReply &reply, QByteDataBuffer &data); + void appendCompressedData(QHttpNetworkReply &reply, QByteDataBuffer &data); qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const; qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const; qint64 compressedBytesAvailable(const QHttpNetworkReply &reply) const; - qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize); - void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode); bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend); void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply); diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 7a616aa..2fe0d78 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -176,15 +176,6 @@ qint64 QHttpNetworkReply::bytesAvailableNextBlock() const return -1; } -QByteArray QHttpNetworkReply::read(qint64 maxSize) -{ - Q_D(QHttpNetworkReply); - QByteArray data; - if (d->connection) - d->connection->d_func()->read(*this, data, maxSize); - return data; -} - QByteArray QHttpNetworkReply::readAny() { Q_D(QHttpNetworkReply); @@ -203,7 +194,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), chunkedTransferEncoding(0), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), - autoDecompress(false), responseData(0), requestIsPrepared(false) + autoDecompress(false), responseData(), requestIsPrepared(false) { } @@ -561,17 +552,19 @@ bool QHttpNetworkReplyPrivate::connectionCloseEnabled() // note this function can only be used for non-chunked, non-compressed with // known content length -qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QRingBuffer *rb) -{ - quint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); - char* dst = rb->reserve(toBeRead); - qint64 haveRead = socket->read(dst, toBeRead); +qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb) +{ + qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); + QByteArray bd; + bd.resize(toBeRead); + qint64 haveRead = socket->read(bd.data(), bd.size()); if (haveRead == -1) { - rb->chop(toBeRead); + bd.clear(); return 0; // ### error checking here; } + bd.resize(haveRead); - rb->chop(toBeRead - haveRead); + rb->append(bd); if (contentRead + haveRead == bodyLength) { state = AllDoneState; @@ -583,7 +576,7 @@ qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QRingBuff } -qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out) +qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuffer *out) { qint64 bytes = 0; if (isChunked()) { @@ -601,33 +594,35 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size) { qint64 bytes = 0; Q_ASSERT(in); Q_ASSERT(out); int toBeRead = qMin(128*1024, qMin(size, in->bytesAvailable())); - QByteArray raw(toBeRead, 0); - while (size > 0) { - qint64 read = in->read(raw.data(), raw.size()); - if (read == 0) - return bytes; - // ### error checking here - qint64 written = out->write(raw.data(), read); - if (written == 0) + while (toBeRead > 0) { + QByteArray byteData; + byteData.resize(toBeRead); + qint64 haveRead = in->read(byteData.data(), byteData.size()); + if (haveRead <= 0) { + // ### error checking here + byteData.clear(); return bytes; - if (read != written) - qDebug() << "### read" << read << "written" << written; - bytes += read; - size -= read; - out->waitForBytesWritten(-1); // throttle + } + + byteData.resize(haveRead); + out->append(byteData); + bytes += haveRead; + size -= haveRead; + + toBeRead = qMin(128*1024, qMin(size, in->bytesAvailable())); } return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QIODevice *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out) { qint64 bytes = 0; while (in->bytesAvailable()) { // while we can read from input @@ -648,17 +643,14 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QIODevice * state = AllDoneState; break; } - // otherwise, read data - qint64 readSize = qMin(in->bytesAvailable(), currentChunkSize - currentChunkRead); - QByteArray buffer(readSize, 0); - qint64 read = in->read(buffer.data(), readSize); - bytes += read; - currentChunkRead += read; - qint64 written = out->write(buffer); - Q_UNUSED(written); // Avoid compile warning when building release - Q_ASSERT(read == written); + + // otherwise, try to read what is missing for this chunk + qint64 haveRead = readReplyBodyRaw (in, out, currentChunkSize - currentChunkRead); + currentChunkRead += haveRead; + bytes += haveRead; + // ### error checking here - out->waitForBytesWritten(-1); + } return bytes; } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 5eb70ce..fbbee12 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -80,6 +80,7 @@ static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header #include #include #include +#include QT_BEGIN_NAMESPACE @@ -122,7 +123,6 @@ public: qint64 bytesAvailable() const; qint64 bytesAvailableNextBlock() const; - QByteArray read(qint64 maxSize = -1); QByteArray readAny(); bool isFinished() const; @@ -160,14 +160,14 @@ public: bool parseStatus(const QByteArray &status); qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); - qint64 readBody(QAbstractSocket *socket, QIODevice *out); - qint64 readBodyFast(QAbstractSocket *socket, QRingBuffer *rb); + qint64 readBody(QAbstractSocket *socket, QByteDataBuffer *out); + qint64 readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb); bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); - qint64 readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size); - qint64 readReplyBodyChunked(QIODevice *in, QIODevice *out); + qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); + qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out); qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); qint64 bytesAvailable() const; @@ -209,7 +209,7 @@ public: #endif bool autoDecompress; - QRingBuffer responseData; // uncompressed body + QByteDataBuffer responseData; // uncompressed body QByteArray compressedData; // compressed body (temporary) bool requestIsPrepared; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 88ae894..9e17b54 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -217,9 +217,9 @@ qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const return reply->nextDownstreamBlockSize(); } -void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data) +void QNetworkAccessBackend::writeDownstreamData(QByteDataBuffer &list) { - reply->appendDownstreamData(data); + reply->appendDownstreamData(list); } void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 21cb4a6..553b795 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -166,7 +166,7 @@ protected: // these functions control the downstream mechanism // that is, data that has come via the connection and is going out the backend qint64 nextDownstreamBlockSize() const; - void writeDownstreamData(const QByteArray &data); + void writeDownstreamData(QByteDataBuffer &list); public slots: // for task 251801, needs to be a slot to be called asynchronously diff --git a/src/network/access/qnetworkaccessdatabackend.cpp b/src/network/access/qnetworkaccessdatabackend.cpp index 609f0c5..4436cf4 100644 --- a/src/network/access/qnetworkaccessdatabackend.cpp +++ b/src/network/access/qnetworkaccessdatabackend.cpp @@ -117,7 +117,11 @@ void QNetworkAccessDataBackend::open() setHeader(QNetworkRequest::ContentLengthHeader, payload.size()); emit metaDataChanged(); - writeDownstreamData(payload); + QByteDataBuffer list; + list.append(payload); + payload.clear(); // important because of implicit sharing! + writeDownstreamData(list); + finished(); return; } diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp index 54fcddd..2b3c128 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend.cpp +++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp @@ -155,7 +155,11 @@ void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream() // have read something buffer.resize(haveRead); bytesDownloaded += haveRead; - writeDownstreamData(buffer); + + QByteDataBuffer list; + list.append(buffer); + buffer.clear(); // important because of implicit sharing! + writeDownstreamData(list); } } } diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index e3fc8bf..533fc75 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -263,7 +263,11 @@ bool QNetworkAccessFileBackend::readMoreFromFile() data.resize(actuallyRead); totalBytes += actuallyRead; - writeDownstreamData(data); + + QByteDataBuffer list; + list.append(data); + data.clear(); // important because of implicit sharing! + writeDownstreamData(list); } return true; } diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index d6276a3..911b31a 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -355,7 +355,11 @@ void QNetworkAccessFtpBackend::ftpDone() void QNetworkAccessFtpBackend::ftpReadyRead() { - writeDownstreamData(ftp->readAll()); + QByteArray data = ftp->readAll(); + QByteDataBuffer list; + list.append(data); + data.clear(); // important because of implicit sharing! + writeDownstreamData(list); } void QNetworkAccessFtpBackend::ftpRawCommandReply(int code, const QString &text) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index db84e58..9c36026 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -653,10 +653,15 @@ void QNetworkAccessHttpBackend::readFromHttp() // this is not a critical thing since it is already in the // memory anyway - while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0) { - const QByteArray data = httpReply->readAny(); - writeDownstreamData(data); + QByteDataBuffer list; + + while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) { + QByteArray data = httpReply->readAny(); + list.append(data); } + + if (!list.isEmpty()) + writeDownstreamData(list); } void QNetworkAccessHttpBackend::replyFinished() diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 55b8b7f..44ae328 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -103,16 +103,17 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() break; bytesToRead = qBound(1, bytesToRead, copyDevice->bytesAvailable()); - char *ptr = readBuffer.reserve(bytesToRead); - qint64 bytesActuallyRead = copyDevice->read(ptr, bytesToRead); + QByteArray byteData; + byteData.resize(bytesToRead); + qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size()); if (bytesActuallyRead == -1) { - readBuffer.chop(bytesToRead); + byteData.clear(); backendNotify(NotifyCopyFinished); break; } - if (bytesActuallyRead != bytesToRead) - readBuffer.chop(bytesToRead - bytesActuallyRead); + byteData.resize(bytesActuallyRead); + readBuffer.append(byteData); if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); @@ -384,19 +385,17 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const if (readBufferMaxSize == 0) return DesiredBufferSize; - return qMax(0, readBufferMaxSize - readBuffer.size()); + return qMax(0, readBufferMaxSize - readBuffer.byteAmount()); } // we received downstream data and send this to the cache // and to our readBuffer (which in turn gets read by the user of QNetworkReply) -void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) +void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) { Q_Q(QNetworkReplyImpl); if (!q->isOpen()) return; - readBuffer.append(data); - if (cacheEnabled && !cacheSaveDevice) { // save the meta data QNetworkCacheMetaData metaData; @@ -415,10 +414,19 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) } } - if (cacheSaveDevice) - cacheSaveDevice->write(data); + qint64 bytesWritten = 0; + for (int i = 0; i < data.bufferCount(); i++) { + QByteArray item = data[i]; + + if (cacheSaveDevice) + cacheSaveDevice->write(item.constData(), item.size()); + readBuffer.append(item); + + bytesWritten += item.size(); + } + data.clear(); - bytesDownloaded += data.size(); + bytesDownloaded += bytesWritten; lastBytesDownloaded = bytesDownloaded; QPointer qq = q; @@ -427,6 +435,8 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); + // important: At the point of this readyRead(), the data parameter list must be empty, + // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); // hopefully we haven't been deleted here @@ -602,14 +612,14 @@ void QNetworkReplyImpl::close() */ qint64 QNetworkReplyImpl::bytesAvailable() const { - return QNetworkReply::bytesAvailable() + d_func()->readBuffer.size(); + return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount(); } void QNetworkReplyImpl::setReadBufferSize(qint64 size) { Q_D(QNetworkReplyImpl); if (size > d->readBufferMaxSize && - size == d->readBuffer.size()) + size > d->readBuffer.byteAmount()) d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); QNetworkReply::setReadBufferSize(size); @@ -657,7 +667,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) return 1; } - maxlen = qMin(maxlen, d->readBuffer.size()); + maxlen = qMin(maxlen, d->readBuffer.byteAmount()); return d->readBuffer.read(data, maxlen); } diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 454185a..83a8aca 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -61,6 +61,7 @@ #include "QtCore/qqueue.h" #include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" +#include "private/qbytedata_p.h" QT_BEGIN_NAMESPACE @@ -144,7 +145,7 @@ public: void consume(qint64 count); void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal); qint64 nextDownstreamBlockSize() const; - void appendDownstreamData(const QByteArray &data); + void appendDownstreamData(QByteDataBuffer &data); void appendDownstreamData(QIODevice *data); void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); @@ -172,7 +173,7 @@ public: QList proxyList; #endif - QRingBuffer readBuffer; + QByteDataBuffer readBuffer; qint64 bytesDownloaded; qint64 lastBytesDownloaded; qint64 bytesUploaded; -- cgit v0.12 From 1aa43fc4af995374c577a951fd2054d696aa3b14 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 16 Jul 2009 21:13:13 +0200 Subject: Fixes: ItemView text editor is not visible with empty text and icons It was not visible wicause its height was 0 Task-number: 257481 Reviewed-by: mbm --- src/gui/itemviews/qitemdelegate.cpp | 6 +- src/gui/styles/qcommonstyle.cpp | 14 +++- .../qabstractitemview/tst_qabstractitemview.cpp | 83 ++++++++++++++++------ 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index a285113..336ca79 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -861,6 +861,8 @@ void QItemDelegate::drawBackground(QPainter *painter, /*! \internal + + Code duplicated in QCommonStylePrivate::viewItemLayout */ void QItemDelegate::doLayout(const QStyleOptionViewItem &option, @@ -882,8 +884,10 @@ void QItemDelegate::doLayout(const QStyleOptionViewItem &option, int w, h; textRect->adjust(-textMargin, 0, textMargin, 0); // add width padding - if (textRect->height() == 0 && !hasPixmap) + if (textRect->height() == 0 && (!hasPixmap || !hint)) { + //if there is no text, we still want to have a decent height for the item sizeHint and the editor size textRect->setHeight(option.fontMetrics.height()); + } QSize pm(0, 0); if (hasPixmap) { diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 29176c3..aba89bc 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -1182,8 +1182,14 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt } } -/* Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore - opt->rect and return rectangles in infinite space */ +/*! \internal + compute the position for the different component of an item (pixmap, text, checkbox) + + Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore + opt->rect and return rectangles in infinite space + + Code duplicated in QItemDelegate::doLayout +*/ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRect *checkRect, QRect *pixmapRect, QRect *textRect, bool sizehint) const { @@ -1204,8 +1210,10 @@ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRe int y = opt->rect.top(); int w, h; - if (textRect->height() == 0 && !hasPixmap) + if (textRect->height() == 0 && (!hasPixmap || !sizehint)) { + //if there is no text, we still want to have a decent height for the item sizeHint and the editor size textRect->setHeight(opt->fontMetrics.height()); + } QSize pm(0, 0); if (hasPixmap) { diff --git a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/qabstractitemview/tst_qabstractitemview.cpp index 0bc459e..e7b94d1 100644 --- a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/qabstractitemview/tst_qabstractitemview.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include "../../shared/util.h" //TESTED_CLASS= @@ -209,10 +210,11 @@ private slots: void noFallbackToRoot(); void setCurrentIndex_data(); void setCurrentIndex(); - + void task221955_selectedEditor(); void task250754_fontChange(); void task200665_itemEntered(); + void task257481_emptyEditor(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -945,12 +947,12 @@ void tst_QAbstractItemView::dragAndDropOnChild() class TestModel : public QStandardItemModel { public: - TestModel(int rows, int columns) : QStandardItemModel(rows, columns) + TestModel(int rows, int columns) : QStandardItemModel(rows, columns) { setData_count = 0; } - virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/) + virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/) { ++setData_count; return true; @@ -967,20 +969,20 @@ void tst_QAbstractItemView::setItemDelegate_data() // default is rows, a -1 will switch to columns QTest::addColumn("rowsOrColumnsWithDelegate"); QTest::addColumn("cellToEdit"); - QTest::newRow("4 columndelegates") - << (IntList() << -1 << 0 << 1 << 2 << 3) + QTest::newRow("4 columndelegates") + << (IntList() << -1 << 0 << 1 << 2 << 3) << QPoint(0, 0); - QTest::newRow("2 identical rowdelegates on the same row") - << (IntList() << 0 << 0) + QTest::newRow("2 identical rowdelegates on the same row") + << (IntList() << 0 << 0) << QPoint(0, 0); - QTest::newRow("2 identical columndelegates on the same column") - << (IntList() << -1 << 2 << 2) + QTest::newRow("2 identical columndelegates on the same column") + << (IntList() << -1 << 2 << 2) << QPoint(2, 0); - QTest::newRow("2 duplicate delegates, 1 row and 1 column") - << (IntList() << 0 << -1 << 2) + QTest::newRow("2 duplicate delegates, 1 row and 1 column") + << (IntList() << 0 << -1 << 2) << QPoint(2, 0); - QTest::newRow("4 duplicate delegates, 2 row and 2 column") - << (IntList() << 0 << 0 << -1 << 2 << 2) + QTest::newRow("4 duplicate delegates, 2 row and 2 column") + << (IntList() << 0 << 0 << -1 << 2 << 2) << QPoint(2, 0); } @@ -1002,7 +1004,7 @@ void tst_QAbstractItemView::setItemDelegate() if (row) { v.setItemDelegateForRow(rc, delegate); } else { - v.setItemDelegateForColumn(rc, delegate); + v.setItemDelegateForColumn(rc, delegate); } } } @@ -1120,42 +1122,42 @@ void tst_QAbstractItemView::setCurrentIndex() void tst_QAbstractItemView::task221955_selectedEditor() { QPushButton *button; - + QTreeWidget tree; tree.setColumnCount(2); tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Foo" <<"1")); tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Bar" <<"2")); tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Baz" <<"3")); - + QTreeWidgetItem *dummy = new QTreeWidgetItem(); tree.addTopLevelItem(dummy); tree.setItemWidget(dummy, 0, button = new QPushButton("More...")); button->setAutoFillBackground(true); // as recommended in doc - + tree.show(); tree.setFocus(); tree.setCurrentIndex(tree.model()->index(1,0)); QTest::qWait(100); QApplication::setActiveWindow(&tree); - + QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); //We set the focus to the button, the index need to be selected - button->setFocus(); + button->setFocus(); QTest::qWait(100); QVERIFY(tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); - + tree.setCurrentIndex(tree.model()->index(1,0)); QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); - + //Same thing but with the flag NoSelection, nothing can be selected. tree.setFocus(); tree.setSelectionMode(QAbstractItemView::NoSelection); tree.clearSelection(); QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty()); QTest::qWait(10); - button->setFocus(); + button->setFocus(); QTest::qWait(50); QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty()); } @@ -1196,7 +1198,7 @@ void tst_QAbstractItemView::task250754_fontChange() QTest::qWait(30); //now with the huge items, the scrollbar must be visible QVERIFY(tree.verticalScrollBar()->isVisible()); - + qApp->setStyleSheet(app_css); } @@ -1217,6 +1219,41 @@ void tst_QAbstractItemView::task200665_itemEntered() } +void tst_QAbstractItemView::task257481_emptyEditor() +{ + QIcon icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon); + + QStandardItemModel model; + + model.appendRow( new QStandardItem(icon, QString()) ); + model.appendRow( new QStandardItem(icon, "Editor works") ); + model.appendRow( new QStandardItem( QString() ) ); + + QTreeView treeView; + treeView.setRootIsDecorated(false); + treeView.setModel(&model); + treeView.show(); + + treeView.edit(model.index(0,0)); + QList lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(1,0)); + lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(2,0)); + lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" -- cgit v0.12 From 05ae1e2cf1c1d95377b302a6b4599358107c63b1 Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Fri, 17 Jul 2009 13:44:44 +0200 Subject: Doc: Added info on QWrappedEvent to QAbstractTransition::eventTest() Reviewed-by: Kent Hansen --- doc/src/snippets/statemachine/eventtest.cpp | 34 ++++++++++++++++++++++++ src/corelib/kernel/qcoreevent.cpp | 2 +- src/corelib/statemachine/qabstracttransition.cpp | 12 +++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 doc/src/snippets/statemachine/eventtest.cpp diff --git a/doc/src/snippets/statemachine/eventtest.cpp b/doc/src/snippets/statemachine/eventtest.cpp new file mode 100644 index 0000000..e0f359a --- /dev/null +++ b/doc/src/snippets/statemachine/eventtest.cpp @@ -0,0 +1,34 @@ + +#include + +class MyTransition : public QAbstractTransition +{ + Q_OBJECT +public: + MyTransition() {} + +protected: +//![0] + bool eventTest(QEvent *event) + { + if (event->type() == QEvent::Wrapped) { + QEvent *wrappedEvent = static_cast(event)->event(); + if (wrappedEvent->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(wrappedEvent); + // Do your event test + } + } + return false; + } +//![0] + + void onTransition(QEvent *event) + { + + } +}; + +int main(int argv, char **args) +{ + return 0; +} diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index c636716..a682fad9 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -219,6 +219,7 @@ QT_BEGIN_NAMESPACE \value WindowStateChange The \l{QWidget::windowState()}{window's state} (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent). \value WindowTitleChange The window title has changed. \value WindowUnblocked The window is unblocked after a modal dialog exited. + \value Wrapped The event is a wrapper for, i.e., contains, another event (QWrappedEvent). \value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows. \value KeyboardLayoutChange The keyboard layout has changed. \value DynamicPropertyChange A dynamic property was added, changed or removed from the object. @@ -267,7 +268,6 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal - \omitvalue Wrapped \omitvalue Signal \omitvalue WinGesture */ diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 670aa7d..c040c58 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -330,6 +330,18 @@ QList QAbstractTransition::animations() const This function is called to determine whether the given \a event should cause this transition to trigger. Reimplement this function and return true if the event should trigger the transition, otherwise return false. + + + Note that \a event is a QWrappedEvent, which contains a clone of + the event generated by Qt. For instance, if you want to check a + key press event, do the following: + + \snippet doc/src/snippets/statemachine/eventtest.cpp 0 + + You need to check if \a event is a QWrappedEvent because Qt also + uses other events for internal reasons; you don't need to concern + yourself with these in any case. + */ /*! -- cgit v0.12 From 587de884fadba615f86154747e116c8d6cd196e3 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Fri, 17 Jul 2009 13:52:45 +0200 Subject: Fixes: Do not create a mapping for filtered items in QSortFilterProxyModel. Task: 258227 Details: This patch fixes the problem where items that are filtered, can sometime still have a mapping. This creates a problem when they become visible again, and the outdated mapping already exists. --- src/gui/itemviews/qsortfilterproxymodel.cpp | 42 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 30a8c96..fdc09ca 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -146,6 +146,7 @@ public: const QModelIndex &source_parent) const; QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const; QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const; + bool can_create_mapping(const QModelIndex &source_parent) const; void remove_from_mapping(const QModelIndex &source_parent); @@ -354,6 +355,25 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou return create_index(proxy_row, proxy_column, it); } +bool QSortFilterProxyModelPrivate::can_create_mapping(const QModelIndex &source_parent) const +{ + if (source_parent.isValid()) { + QModelIndex source_grand_parent = source_parent.parent(); + IndexMap::const_iterator it = source_index_mapping.constFind(source_grand_parent); + if (it == source_index_mapping.constEnd()) { + // Don't care, since we don't have mapping for the grand parent + return false; + } + Mapping *gm = it.value(); + if (gm->proxy_rows.at(source_parent.row()) == -1 || + gm->proxy_columns.at(source_parent.column()) == -1) { + // Don't care, since parent is filtered + return false; + } + } + return true; +} + /*! \internal @@ -659,20 +679,8 @@ void QSortFilterProxyModelPrivate::source_items_inserted( return; IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); if (it == source_index_mapping.constEnd()) { - if (source_parent.isValid()) { - QModelIndex source_grand_parent = source_parent.parent(); - it = source_index_mapping.constFind(source_grand_parent); - if (it == source_index_mapping.constEnd()) { - // Don't care, since we don't have mapping for the grand parent - return; - } - Mapping *gm = it.value(); - if (gm->proxy_rows.at(source_parent.row()) == -1 || - gm->proxy_columns.at(source_parent.column()) == -1) { - // Don't care, since parent is filtered - return; - } - } + if (!can_create_mapping(source_parent)) + return; it = create_mapping(source_parent); Mapping *m = it.value(); QModelIndex proxy_parent = q->mapFromSource(source_parent); @@ -1186,7 +1194,8 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted( Q_UNUSED(end); //Force the creation of a mapping now, even if its empty. //We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items - create_mapping(source_parent); + if (can_create_mapping(source_parent)) + create_mapping(source_parent); } void QSortFilterProxyModelPrivate::_q_sourceRowsInserted( @@ -1217,7 +1226,8 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted( Q_UNUSED(end); //Force the creation of a mapping now, even if its empty. //We need it because the proxy can be acessed at the moment it emits columnsAboutToBeInserted in insert_source_items - create_mapping(source_parent); + if (can_create_mapping(source_parent)) + create_mapping(source_parent); } void QSortFilterProxyModelPrivate::_q_sourceColumnsInserted( -- cgit v0.12 From c0dfc3f7cedb889e8d68161080262e715165e771 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Fri, 17 Jul 2009 13:29:27 +0200 Subject: Handle Jens' new variable. In theory, the new "follow style" value will never be hit, let's make that explicit in the code. --- src/gui/styles/qmacstyle_mac.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 5d75392..b615918 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -3361,6 +3361,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); break; } + default: + Q_ASSERT(false); + break; } if (needText) { -- cgit v0.12 From 68c0e6a8ba1e92bf0152adcaa86eebb83dcfd1d8 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Fri, 17 Jul 2009 13:32:21 +0200 Subject: Move QMacStyle icon handling down to the common style. This is more follow the cue of what is done on X11, mainly, if you are creating things like messageboxes or file views, you want them to follow the desktop (yes, you do). If you disable desktop settings aware, you get the old look. This also meant shifting around some functions into qt_cocoa_helpers_mac to make them more readily available instead of living in differnt files. People who use standard pixmap get the old values, but I think that's fine. If you haven't moved onto standardIcon (introduced in 4.1), you don't get the latest bling. Review-by: Jens Bache-Wiig --- src/gui/image/qpixmap_mac.cpp | 19 ----- src/gui/itemviews/qfileiconprovider.cpp | 7 +- src/gui/kernel/qt_cocoa_helpers_mac.mm | 46 ++++++++++++ src/gui/kernel/qt_cocoa_helpers_mac_p.h | 3 + src/gui/styles/qcommonstyle.cpp | 111 +++++++++++++++++++++++++++-- src/gui/styles/qmacstyle_mac.mm | 122 +------------------------------- 6 files changed, 162 insertions(+), 146 deletions(-) diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index c281fe9..25ef8ba 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -1169,25 +1169,6 @@ IconRef qt_mac_create_iconref(const QPixmap &px) } #endif -QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) -{ - QPixmap ret(width, height); - ret.fill(QColor(0, 0, 0, 0)); - - CGRect rect = CGRectMake(0, 0, width, height); - - CGContextRef ctx = qt_mac_cg_context(&ret); - CGAffineTransform old_xform = CGContextGetCTM(ctx); - CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(ctx, CGAffineTransformIdentity); - - ::RGBColor b; - b.blue = b.green = b.red = 255*255; - PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); - CGContextRelease(ctx); - return ret; -} - /*! \internal */ QPaintEngine* QMacPixmapData::paintEngine() const { diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index 1856f4d..53608e7 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -53,7 +53,7 @@ #include #include #elif defined(Q_WS_MAC) -#include +#include #endif #include @@ -326,10 +326,11 @@ QIcon QFileIconProviderPrivate::getMacIcon(const QFileInfo &fi) const return retIcon; IconRef iconRef; SInt16 iconLabel; - status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode, kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag, &iconRef, &iconLabel); + status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode, + kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag, + &iconRef, &iconLabel); if (status != noErr) return retIcon; - extern void qt_mac_constructQIconFromIconRef(const IconRef, const IconRef, QIcon*, QStyle::StandardPixmap = QStyle::SP_CustomBase); // qmacstyle_mac.cpp qt_mac_constructQIconFromIconRef(iconRef, 0, &retIcon); ReleaseIconRef(iconRef); return retIcon; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index a98a7f8..223e36b 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -1147,4 +1148,49 @@ QString qt_mac_get_pasteboardString() } } +QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) +{ + QPixmap ret(width, height); + ret.fill(QColor(0, 0, 0, 0)); + + CGRect rect = CGRectMake(0, 0, width, height); + + CGContextRef ctx = qt_mac_cg_context(&ret); + CGAffineTransform old_xform = CGContextGetCTM(ctx); + CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); + CGContextConcatCTM(ctx, CGAffineTransformIdentity); + + ::RGBColor b; + b.blue = b.green = b.red = 255*255; + PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); + CGContextRelease(ctx); + return ret; +} + +void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon) +{ + int size = 16; + while (size <= 128) { + + const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size); + QPixmap mainIcon; + if (standardIcon >= QStyle::SP_CustomBase) { + mainIcon = qt_mac_convert_iconref(icon, size, size); + } else if (QPixmapCache::find(cacheKey, mainIcon) == false) { + mainIcon = qt_mac_convert_iconref(icon, size, size); + QPixmapCache::insert(cacheKey, mainIcon); + } + + if (overlayIcon) { + int littleSize = size / 2; + QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize); + QPainter painter(&mainIcon); + painter.drawPixmap(size - littleSize, size - littleSize, overlayPix); + } + + retIcon->addPixmap(mainIcon); + size += size; // 16 -> 32 -> 64 -> 128 + } +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 5f6204f..99f058b 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -143,6 +143,9 @@ struct ::TabletProximityRec; void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec); Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags); Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations); +QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height); +void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, + QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase); inline int flipYCoordinate(int y) { return QApplication::desktop()->screenGeometry(0).height() - y; diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index aba89bc..308a0b8 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -84,6 +84,8 @@ #ifdef Q_WS_X11 # include +#elif defined(Q_WS_MAC) +# include #endif QT_BEGIN_NAMESPACE @@ -4876,7 +4878,14 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid ret = int(QStyleHelper::dpiScaled(13.)); break; case PM_MessageBoxIconSize: - ret = int(QStyleHelper::dpiScaled(32.)); +#ifdef Q_WS_MAC + if (QApplication::desktopSettingsAware()) { + ret = 64; // No DPI scaling, it's handled elsewhere. + } else +#endif + { + ret = int(QStyleHelper::dpiScaled(32.)); + } break; case PM_TextCursorWidth: ret = 1; @@ -5774,9 +5783,9 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons const QWidget *widget) const { QIcon icon; -#ifdef Q_WS_X11 - Q_D(const QCommonStyle); if (QApplication::desktopSettingsAware()) { +#ifdef Q_WS_X11 + Q_D(const QCommonStyle); d->lookupIconTheme(); QPixmap pixmap; switch (standardIcon) { @@ -5795,6 +5804,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons case SP_MessageBoxWarning: { icon = d->createIcon(QLatin1String("dialog-warning.png")); + icon = d->createIcon(QLatin1String("dialog-warning.png")); if (icon.isNull()) icon = d->createIcon(QLatin1String("messagebox_warning.png")); break; @@ -6020,8 +6030,101 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons } if (!icon.isNull()) return icon; +#elif defined(Q_WS_MAC) + OSType iconType = 0; + switch (standardIcon) { + case QStyle::SP_MessageBoxQuestion: + case QStyle::SP_MessageBoxInformation: + case QStyle::SP_MessageBoxWarning: + case QStyle::SP_MessageBoxCritical: + iconType = kGenericApplicationIcon; + break; + case SP_DesktopIcon: + iconType = kDesktopIcon; + break; + case SP_TrashIcon: + iconType = kTrashIcon; + break; + case SP_ComputerIcon: + iconType = kComputerIcon; + break; + case SP_DriveFDIcon: + iconType = kGenericFloppyIcon; + break; + case SP_DriveHDIcon: + iconType = kGenericHardDiskIcon; + break; + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + iconType = kGenericCDROMIcon; + break; + case SP_DriveNetIcon: + iconType = kGenericNetworkIcon; + break; + case SP_DirOpenIcon: + iconType = kOpenFolderIcon; + break; + case SP_DirClosedIcon: + case SP_DirLinkIcon: + iconType = kGenericFolderIcon; + break; + case SP_FileLinkIcon: + case SP_FileIcon: + iconType = kGenericDocumentIcon; + break; + case SP_DirIcon: { + // A rather special case + QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, option, widget); + QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, option, widget); + closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On); + return closeIcon; } -#endif//Q_WS_X11 + case SP_TitleBarNormalButton: + case SP_TitleBarCloseButton: { + QIcon titleBarIcon; + if (standardIcon == SP_TitleBarCloseButton) { + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-16.png")); + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); + } else { + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-16.png")); + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); + } + return titleBarIcon; + } + default: + break; + } + if (iconType != 0) { + QIcon retIcon; + IconRef icon; + IconRef overlayIcon = 0; + if (iconType != kGenericApplicationIcon) { + GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); + } else { + FSRef fsRef; + ProcessSerialNumber psn = { 0, kCurrentProcess }; + GetProcessBundleLocation(&psn, &fsRef); + GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0); + if (standardIcon == SP_MessageBoxCritical) { + overlayIcon = icon; + GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon); + } + } + if (icon) { + qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon); + ReleaseIconRef(icon); + } + if (overlayIcon) + ReleaseIconRef(overlayIcon); + return retIcon; + } + +#endif //Q_WS_X11 || Q_WS_MAC + } + switch (standardIcon) { #ifndef QT_NO_IMAGEFORMAT_PNG diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index b615918..2f93034 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -558,7 +558,6 @@ QT_END_INCLUDE_NAMESPACE External functions *****************************************************************************/ extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp -extern QPixmap qt_mac_convert_iconref(const IconRef, int, int); //qpixmap_mac.cpp extern QRegion qt_mac_convert_mac_region(HIShapeRef); //qregion_mac.cpp void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp @@ -2303,9 +2302,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW case PM_ToolBarItemSpacing: ret = 4; break; - case PM_MessageBoxIconSize: - ret = 64; - break; case PM_SplitterWidth: ret = qMax(7, QApplication::globalStrut().width()); break; @@ -5858,76 +5854,12 @@ bool QMacStyle::event(QEvent *e) return false; } -void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase) -{ - int size = 16; - while (size <= 128) { - - const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size); - QPixmap mainIcon; - if (standardIcon >= QStyle::SP_CustomBase) { - mainIcon = qt_mac_convert_iconref(icon, size, size); - } else if (QPixmapCache::find(cacheKey, mainIcon) == false) { - mainIcon = qt_mac_convert_iconref(icon, size, size); - QPixmapCache::insert(cacheKey, mainIcon); - } - - if (overlayIcon) { - int littleSize = size / 2; - QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize); - QPainter painter(&mainIcon); - painter.drawPixmap(size - littleSize, size - littleSize, overlayPix); - } - - retIcon->addPixmap(mainIcon); - size += size; // 16 -> 32 -> 64 -> 128 - } -} - QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const { - OSType iconType = 0; switch (standardIcon) { - case QStyle::SP_MessageBoxQuestion: - case QStyle::SP_MessageBoxInformation: - case QStyle::SP_MessageBoxWarning: - case QStyle::SP_MessageBoxCritical: - iconType = kGenericApplicationIcon; - break; - case SP_DesktopIcon: - iconType = kDesktopIcon; - break; - case SP_TrashIcon: - iconType = kTrashIcon; - break; - case SP_ComputerIcon: - iconType = kComputerIcon; - break; - case SP_DriveFDIcon: - iconType = kGenericFloppyIcon; - break; - case SP_DriveHDIcon: - iconType = kGenericHardDiskIcon; - break; - case SP_DriveCDIcon: - case SP_DriveDVDIcon: - iconType = kGenericCDROMIcon; - break; - case SP_DriveNetIcon: - iconType = kGenericNetworkIcon; - break; - case SP_DirOpenIcon: - iconType = kOpenFolderIcon; - break; - case SP_DirClosedIcon: - case SP_DirLinkIcon: - iconType = kGenericFolderIcon; - break; - case SP_FileLinkIcon: - case SP_FileIcon: - iconType = kGenericDocumentIcon; - break; + default: + return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget); case SP_ToolBarHorizontalExtensionButton: case SP_ToolBarVerticalExtensionButton: { QPixmap pixmap(qt_mac_toolbar_ext); @@ -5941,58 +5873,8 @@ QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const Q return pix2; } return pixmap; - } - break; - case SP_DirIcon: { - // A rather special case - QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, opt, widget); - QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, opt, widget); - closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On); - closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On); - closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On); - closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On); - return closeIcon; } - case SP_TitleBarNormalButton: - case SP_TitleBarCloseButton: { - QIcon titleBarIcon; - if (standardIcon == SP_TitleBarCloseButton) { - titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-16.png")); - titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); - } else { - titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-16.png")); - titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); - } - return titleBarIcon; - } - default: - break; - } - if (iconType != 0) { - QIcon retIcon; - IconRef icon; - IconRef overlayIcon = 0; - if (iconType != kGenericApplicationIcon) { - GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); - } else { - FSRef fsRef; - ProcessSerialNumber psn = { 0, kCurrentProcess }; - GetProcessBundleLocation(&psn, &fsRef); - GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0); - if (standardIcon == SP_MessageBoxCritical) { - overlayIcon = icon; - GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon); - } - } - if (icon) { - qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon); - ReleaseIconRef(icon); - } - if (overlayIcon) - ReleaseIconRef(overlayIcon); - return retIcon; } - return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget); } int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, -- cgit v0.12 From 538cbb4f5b638cdfa2fff2576a723457a2c889c6 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Fri, 17 Jul 2009 14:29:39 +0200 Subject: Add reading of kde colors Link and LinkVisited colors from qt apps in qapplication_x11.cpp so these two colors don't get overridden by the defaults when kde config is found. Merge-request: 917 Reviewed-by: Olivier Goffart --- src/gui/kernel/qapplication_x11.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index cc41299..77e29a6 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -1396,6 +1396,18 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"), theKdeSettings); if (color.isValid()) pal.setColor(QPalette::ButtonText, color); + + color = kdeColor(QLatin1String("linkColor"), theKdeSettings); + if (!color.isValid()) + color = kdeColor(QLatin1String("Colors:View/ForegroundLink"), theKdeSettings); + if (color.isValid()) + pal.setColor(QPalette::Link, color); + + color = kdeColor(QLatin1String("visitedLinkColor"), theKdeSettings); + if (!color.isValid()) + color = kdeColor(QLatin1String("Colors:View/ForegroundVisited"), theKdeSettings); + if (color.isValid()) + pal.setColor(QPalette::LinkVisited, color); } if (highlight.isValid() && highlightText.isValid()) { -- cgit v0.12 From e3a34408aa65af33494b7154ab5eaefe676b5f20 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Fri, 17 Jul 2009 14:47:53 +0200 Subject: Update to also use a uifile.icns file for Designer. If we are doing it for Creator, we may as well be nice and do a similar thing for Designer. --- tools/designer/src/designer/Info_mac.plist | 2 +- tools/designer/src/designer/designer.pro | 3 +++ tools/designer/src/designer/uifile.icns | Bin 0 -> 123696 bytes 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 tools/designer/src/designer/uifile.icns diff --git a/tools/designer/src/designer/Info_mac.plist b/tools/designer/src/designer/Info_mac.plist index 8632a6d..f19176f 100644 --- a/tools/designer/src/designer/Info_mac.plist +++ b/tools/designer/src/designer/Info_mac.plist @@ -22,7 +22,7 @@ ui CFBundleTypeIconFile - @ICON@ + uifile.icns CFBundleTypeRole Editor LSIsAppleDefaultForType diff --git a/tools/designer/src/designer/designer.pro b/tools/designer/src/designer/designer.pro index e7fa038..aa6850c 100644 --- a/tools/designer/src/designer/designer.pro +++ b/tools/designer/src/designer/designer.pro @@ -78,6 +78,9 @@ mac { ICON = designer.icns QMAKE_INFO_PLIST = Info_mac.plist TARGET = Designer + FILETYPES.files = uifile.icns + FILETYPES.path = Contents/Resources + QMAKE_BUNDLE_DATA += FILETYPES } target.path=$$[QT_INSTALL_BINS] diff --git a/tools/designer/src/designer/uifile.icns b/tools/designer/src/designer/uifile.icns new file mode 100644 index 0000000..2473ea4 Binary files /dev/null and b/tools/designer/src/designer/uifile.icns differ -- cgit v0.12 From 866e6e6338767086cef8f97bc4e7b38e78b83651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Mercille?= Date: Fri, 17 Jul 2009 14:46:29 +0200 Subject: Lets the size of the completer be configurable in a way similar to QComboBox. Merge-request: 884 Reviewed-by: Olivier Goffart --- examples/tools/completer/mainwindow.cpp | 24 +++++++++-- examples/tools/completer/mainwindow.h | 3 ++ src/gui/util/qcompleter.cpp | 30 ++++++++++++-- src/gui/util/qcompleter.h | 4 ++ src/gui/util/qcompleter_p.h | 1 + tests/auto/qcompleter/tst_qcompleter.cpp | 68 ++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 7 deletions(-) diff --git a/examples/tools/completer/mainwindow.cpp b/examples/tools/completer/mainwindow.cpp index 8ea1c39..06f16de 100644 --- a/examples/tools/completer/mainwindow.cpp +++ b/examples/tools/completer/mainwindow.cpp @@ -75,6 +75,12 @@ MainWindow::MainWindow(QWidget *parent) caseCombo->addItem(tr("Case Insensitive")); caseCombo->addItem(tr("Case Sensitive")); caseCombo->setCurrentIndex(0); + + QLabel *maxVisibleLabel = new QLabel; + maxVisibleLabel->setText(tr("Max Visible Items")); + maxVisibleSpinBox = new QSpinBox; + maxVisibleSpinBox->setRange(3,25); + maxVisibleSpinBox->setValue(10); //! [0] //! [1] @@ -90,6 +96,7 @@ MainWindow::MainWindow(QWidget *parent) connect(modelCombo, SIGNAL(activated(int)), this, SLOT(changeModel())); connect(modeCombo, SIGNAL(activated(int)), this, SLOT(changeMode(int))); connect(caseCombo, SIGNAL(activated(int)), this, SLOT(changeCase(int))); + connect(maxVisibleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeMaxVisible(int))); //! [2] //! [3] @@ -99,9 +106,10 @@ MainWindow::MainWindow(QWidget *parent) layout->addWidget(modelLabel, 0, 0); layout->addWidget(modelCombo, 0, 1); layout->addWidget(modeLabel, 1, 0); layout->addWidget(modeCombo, 1, 1); layout->addWidget(caseLabel, 2, 0); layout->addWidget(caseCombo, 2, 1); - layout->addWidget(wrapCheckBox, 3, 0); - layout->addWidget(contentsLabel, 4, 0, 1, 2); - layout->addWidget(lineEdit, 5, 0, 1, 2); + layout->addWidget(maxVisibleLabel, 3, 0); layout->addWidget(maxVisibleSpinBox, 3, 1); + layout->addWidget(wrapCheckBox, 4, 0); + layout->addWidget(contentsLabel, 5, 0, 1, 2); + layout->addWidget(lineEdit, 6, 0, 1, 2); centralWidget->setLayout(layout); setCentralWidget(centralWidget); @@ -205,6 +213,7 @@ void MainWindow::changeModel() { delete completer; completer = new QCompleter(this); + completer->setMaxVisibleItems(maxVisibleSpinBox->value()); switch (modelCombo->currentIndex()) { default: @@ -256,9 +265,16 @@ void MainWindow::changeModel() //! [14] //! [15] +void MainWindow::changeMaxVisible(int max) +{ + completer->setMaxVisibleItems(max); +} +//! [15] + +//! [16] void MainWindow::about() { QMessageBox::about(this, tr("About"), tr("This example demonstrates the " "different features of the QCompleter class.")); } -//! [15] +//! [16] diff --git a/examples/tools/completer/mainwindow.h b/examples/tools/completer/mainwindow.h index f6c962b..30b8d26 100644 --- a/examples/tools/completer/mainwindow.h +++ b/examples/tools/completer/mainwindow.h @@ -52,6 +52,7 @@ class QLabel; class QLineEdit; class QProgressBar; class QCheckBox; +class QSpinBox; QT_END_NAMESPACE //! [0] @@ -67,6 +68,7 @@ private slots: void changeCase(int); void changeMode(int); void changeModel(); + void changeMaxVisible(int); //! [0] //! [1] @@ -77,6 +79,7 @@ private: QComboBox *caseCombo; QComboBox *modeCombo; QComboBox *modelCombo; + QSpinBox *maxVisibleSpinBox; QCheckBox *wrapCheckBox; QCompleter *completer; QLabel *contentsLabel; diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index d68e309..bf1fa6a 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -134,7 +134,7 @@ To provide completions, QCompleter needs to know the path from an index. This is provided by pathFromIndex(). The default implementation of - pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role} + pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role} for list models and the absolute file path if the mode is a QDirModel. \sa QAbstractItemModel, QLineEdit, QComboBox, {Completer Example} @@ -772,7 +772,7 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& /////////////////////////////////////////////////////////////////////////////// QCompleterPrivate::QCompleterPrivate() : widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0), - sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true) + sorting(QCompleter::UnsortedModel), wrap(true), maxVisibleItems(7), eatFocusOut(true) { } @@ -861,7 +861,7 @@ void QCompleterPrivate::showPopup(const QRect& rect) Qt::LayoutDirection dir = widget->layoutDirection(); QPoint pos; int rw, rh, w; - int h = (popup->sizeHintForRow(0) * qMin(7, popup->model()->rowCount()) + 3) + 3; + int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; QScrollBar *hsb = popup->horizontalScrollBar(); if (hsb && hsb->isVisible()) h += popup->horizontalScrollBar()->sizeHint().height(); @@ -1510,6 +1510,30 @@ bool QCompleter::wrapAround() const } /*! + \property QCompleter::maxVisibleItems + \brief the maximum allowed size on screen of the completer, measured in items + \since 4.6 + + By default, this property has a value of 7. +*/ +int QCompleter::maxVisibleItems() const +{ + Q_D(const QCompleter); + return d->maxVisibleItems; +} + +void QCompleter::setMaxVisibleItems(int maxItems) +{ + Q_D(QCompleter); + if (maxItems < 0) { + qWarning("QCompleter::setMaxVisibleItems: " + "Invalid max visible items (%d) must be >= 0", maxItems); + return; + } + d->maxVisibleItems = maxItems; +} + +/*! \property QCompleter::caseSensitivity \brief the case sensitivity of the matching diff --git a/src/gui/util/qcompleter.h b/src/gui/util/qcompleter.h index c1169ef..a419154 100644 --- a/src/gui/util/qcompleter.h +++ b/src/gui/util/qcompleter.h @@ -69,6 +69,7 @@ class Q_GUI_EXPORT QCompleter : public QObject Q_PROPERTY(CompletionMode completionMode READ completionMode WRITE setCompletionMode) Q_PROPERTY(int completionColumn READ completionColumn WRITE setCompletionColumn) Q_PROPERTY(int completionRole READ completionRole WRITE setCompletionRole) + Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems) Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity) Q_PROPERTY(bool wrapAround READ wrapAround WRITE setWrapAround) @@ -118,6 +119,9 @@ public: bool wrapAround() const; + int maxVisibleItems() const; + void setMaxVisibleItems(int maxItems); + int completionCount() const; bool setCurrentRow(int row); int currentRow() const; diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h index dc4189f..288f531 100644 --- a/src/gui/util/qcompleter_p.h +++ b/src/gui/util/qcompleter_p.h @@ -87,6 +87,7 @@ public: Qt::CaseSensitivity cs; int role; int column; + int maxVisibleItems; QCompleter::ModelSorting sorting; bool wrap; diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index fb03e1a..0a9c16a 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -102,6 +102,8 @@ public: ~tst_QCompleter(); private slots: + void getSetCheck(); + void multipleWidgets(); void focusIn(); @@ -268,6 +270,72 @@ void tst_QCompleter::filter() QCOMPARE(completer->currentCompletion(), completionText); } +// Testing get/set functions +void tst_QCompleter::getSetCheck() +{ + QStandardItemModel model(3,3); + QCompleter completer(&model); + + // QString QCompleter::completionPrefix() + // void QCompleter::setCompletionPrefix(QString) + completer.setCompletionPrefix(QString("te")); + QCOMPARE(completer.completionPrefix(), QString("te")); + completer.setCompletionPrefix(QString()); + QCOMPARE(completer.completionPrefix(), QString()); + + // ModelSorting QCompleter::modelSorting() + // void QCompleter::setModelSorting(ModelSorting) + completer.setModelSorting(QCompleter::CaseSensitivelySortedModel); + QCOMPARE(completer.modelSorting(), QCompleter::CaseSensitivelySortedModel); + completer.setModelSorting(QCompleter::CaseInsensitivelySortedModel); + QCOMPARE(completer.modelSorting(), QCompleter::CaseInsensitivelySortedModel); + completer.setModelSorting(QCompleter::UnsortedModel); + QCOMPARE(completer.modelSorting(), QCompleter::UnsortedModel); + + // CompletionMode QCompleter::completionMode() + // void QCompleter::setCompletionMode(CompletionMode) + QCOMPARE(completer.completionMode(), QCompleter::PopupCompletion); // default value + completer.setCompletionMode(QCompleter::UnfilteredPopupCompletion); + QCOMPARE(completer.completionMode(), QCompleter::UnfilteredPopupCompletion); + completer.setCompletionMode(QCompleter::InlineCompletion); + QCOMPARE(completer.completionMode(), QCompleter::InlineCompletion); + + // int QCompleter::completionColumn() + // void QCompleter::setCompletionColumn(int) + completer.setCompletionColumn(2); + QCOMPARE(completer.completionColumn(), 2); + completer.setCompletionColumn(1); + QCOMPARE(completer.completionColumn(), 1); + + // int QCompleter::completionRole() + // void QCompleter::setCompletionRole(int) + QCOMPARE(completer.completionRole(), static_cast(Qt::EditRole)); // default value + completer.setCompletionRole(Qt::DisplayRole); + QCOMPARE(completer.completionRole(), static_cast(Qt::DisplayRole)); + + // int QCompleter::maxVisibleItems() + // void QCompleter::setMaxVisibleItems(int) + QCOMPARE(completer.maxVisibleItems(), 7); // default value + completer.setMaxVisibleItems(10); + QCOMPARE(completer.maxVisibleItems(), 10); + QTest::ignoreMessage(QtWarningMsg, "QCompleter::setMaxVisibleItems: " + "Invalid max visible items (-2147483648) must be >= 0"); + completer.setMaxVisibleItems(INT_MIN); + QCOMPARE(completer.maxVisibleItems(), 10); // Cannot be set to something negative => old value + + // Qt::CaseSensitivity QCompleter::caseSensitivity() + // void QCompleter::setCaseSensitivity(Qt::CaseSensitivity) + QCOMPARE(completer.caseSensitivity(), Qt::CaseSensitive); // default value + completer.setCaseSensitivity(Qt::CaseInsensitive); + QCOMPARE(completer.caseSensitivity(), Qt::CaseInsensitive); + + // bool QCompleter::wrapAround() + // void QCompleter::setWrapAround(bool) + QCOMPARE(completer.wrapAround(), true); // default value + completer.setWrapAround(false); + QCOMPARE(completer.wrapAround(), false); +} + void tst_QCompleter::csMatchingOnCsSortedModel_data() { delete completer; -- cgit v0.12 From 080231536cbc5e9acc486e57e165320416f66d85 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 17 Jul 2009 15:19:45 +0200 Subject: Update the documentation after the change in the completer exemple --- doc/src/examples/completer.qdoc | 16 ++++++++++++---- examples/tools/completer/mainwindow.cpp | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/src/examples/completer.qdoc b/doc/src/examples/completer.qdoc index 9aaaf66..3805a7c 100644 --- a/doc/src/examples/completer.qdoc +++ b/doc/src/examples/completer.qdoc @@ -100,9 +100,9 @@ \section1 MainWindow Class Definition - The \c MainWindow class is a subclass of QMainWindow and implements four - private slots - \c about(), \c changeCase(), \c changeMode(), and - \c changeModel(). + The \c MainWindow class is a subclass of QMainWindow and implements five + private slots - \c about(), \c changeCase(), \c changeMode(), \c changeModel(), + and \c changeMaxVisible(). \snippet examples/tools/completer/mainwindow.h 0 @@ -126,6 +126,9 @@ \snippet examples/tools/completer/mainwindow.cpp 0 + The \c maxVisibleSpinBox is created and determines the number of visible + item in the completer + The \c wrapCheckBox is then set up. This \c checkBox determines if the \c{completer}'s \l{QCompleter::setWrapAround()}{setWrapAround()} property is enabled or disabled. @@ -242,10 +245,15 @@ \snippet examples/tools/completer/mainwindow.cpp 14 - The \c about() function provides a brief description about the example. + The \c changeMaxVisible() update the maximum number of visible items in + the completer. \snippet examples/tools/completer/mainwindow.cpp 15 + The \c about() function provides a brief description about the example. + + \snippet examples/tools/completer/mainwindow.cpp 16 + \section1 \c main() Function The \c main() function instantiates QApplication and \c MainWindow and diff --git a/examples/tools/completer/mainwindow.cpp b/examples/tools/completer/mainwindow.cpp index 06f16de..c98482a 100644 --- a/examples/tools/completer/mainwindow.cpp +++ b/examples/tools/completer/mainwindow.cpp @@ -75,15 +75,15 @@ MainWindow::MainWindow(QWidget *parent) caseCombo->addItem(tr("Case Insensitive")); caseCombo->addItem(tr("Case Sensitive")); caseCombo->setCurrentIndex(0); +//! [0] +//! [1] QLabel *maxVisibleLabel = new QLabel; maxVisibleLabel->setText(tr("Max Visible Items")); maxVisibleSpinBox = new QSpinBox; maxVisibleSpinBox->setRange(3,25); maxVisibleSpinBox->setValue(10); -//! [0] -//! [1] wrapCheckBox = new QCheckBox; wrapCheckBox->setText(tr("Wrap around completions")); wrapCheckBox->setChecked(true); -- cgit v0.12 From 5f6c0594f07df57af2574be0420a68f84b703b87 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Fri, 17 Jul 2009 13:36:08 +0200 Subject: Add priority property to QAction We need this to support the behavior in Gtk+ where, when Qt::ToolButtonTextBesideIcon is used, only text labels for important actions are shown. It will also enable us to prioritize actions in the future when for instance collapsing a toolbar. Task-number: 258290 Reviewed-by: thierry --- demos/textedit/textedit.cpp | 14 +++++++++++++ src/corelib/global/qnamespace.h | 2 +- src/gui/kernel/qaction.cpp | 27 +++++++++++++++++++++++++- src/gui/kernel/qaction.h | 8 ++++++++ src/gui/kernel/qaction_p.h | 1 + src/gui/styles/qstyle.cpp | 2 +- src/gui/widgets/qtoolbutton.cpp | 10 ++++++++-- tests/auto/qaction/tst_qaction.cpp | 4 ++++ tests/auto/qtoolbutton/tst_qtoolbutton.cpp | 27 ++++++++++++++++++++++++++ tools/assistant/tools/assistant/mainwindow.cpp | 8 +++++++- 10 files changed, 97 insertions(+), 6 deletions(-) diff --git a/demos/textedit/textedit.cpp b/demos/textedit/textedit.cpp index 75a13a5..7f8e1fe 100644 --- a/demos/textedit/textedit.cpp +++ b/demos/textedit/textedit.cpp @@ -159,6 +159,7 @@ void TextEdit::setupFileActions() QAction *a; a = new QAction(QIcon(rsrcPath + "/filenew.png"), tr("&New"), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::New); connect(a, SIGNAL(triggered()), this, SLOT(fileNew())); tb->addAction(a); @@ -180,6 +181,7 @@ void TextEdit::setupFileActions() menu->addAction(a); a = new QAction(tr("Save &As..."), this); + a->setPriority(QAction::LowPriority); connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs())); menu->addAction(a); menu->addSeparator(); @@ -196,6 +198,7 @@ void TextEdit::setupFileActions() menu->addAction(a); a = new QAction(QIcon(rsrcPath + "/exportpdf.png"), tr("&Export PDF..."), this); + a->setPriority(QAction::LowPriority); a->setShortcut(Qt::CTRL + Qt::Key_D); connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf())); tb->addAction(a); @@ -225,19 +228,23 @@ void TextEdit::setupEditActions() tb->addAction(a); menu->addAction(a); a = actionRedo = new QAction(QIcon(rsrcPath + "/editredo.png"), tr("&Redo"), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Redo); tb->addAction(a); menu->addAction(a); menu->addSeparator(); a = actionCut = new QAction(QIcon(rsrcPath + "/editcut.png"), tr("Cu&t"), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Cut); tb->addAction(a); menu->addAction(a); a = actionCopy = new QAction(QIcon(rsrcPath + "/editcopy.png"), tr("&Copy"), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Copy); tb->addAction(a); menu->addAction(a); a = actionPaste = new QAction(QIcon(rsrcPath + "/editpaste.png"), tr("&Paste"), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Paste); tb->addAction(a); menu->addAction(a); @@ -254,6 +261,7 @@ void TextEdit::setupTextActions() menuBar()->addMenu(menu); actionTextBold = new QAction(QIcon(rsrcPath + "/textbold.png"), tr("&Bold"), this); + actionTextBold->setPriority(QAction::LowPriority); actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B); QFont bold; bold.setBold(true); @@ -264,6 +272,7 @@ void TextEdit::setupTextActions() actionTextBold->setCheckable(true); actionTextItalic = new QAction(QIcon(rsrcPath + "/textitalic.png"), tr("&Italic"), this); + actionTextItalic->setPriority(QAction::LowPriority); actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I); QFont italic; italic.setItalic(true); @@ -274,6 +283,7 @@ void TextEdit::setupTextActions() actionTextItalic->setCheckable(true); actionTextUnderline = new QAction(QIcon(rsrcPath + "/textunder.png"), tr("&Underline"), this); + actionTextUnderline->setPriority(QAction::LowPriority); actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U); QFont underline; underline.setUnderline(true); @@ -302,12 +312,16 @@ void TextEdit::setupTextActions() actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); actionAlignLeft->setCheckable(true); + actionAlignLeft->setPriority(QAction::LowPriority); actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E); actionAlignCenter->setCheckable(true); + actionAlignCenter->setPriority(QAction::LowPriority); actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R); actionAlignRight->setCheckable(true); + actionAlignRight->setPriority(QAction::LowPriority); actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); actionAlignJustify->setCheckable(true); + actionAlignJustify->setPriority(QAction::LowPriority); tb->addActions(grp->actions()); menu->addActions(grp->actions()); diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 077e4ef..7770fd6 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1411,7 +1411,7 @@ public: ToolButtonTextOnly, ToolButtonTextBesideIcon, ToolButtonTextUnderIcon, - ToolButtonSystemDefault + ToolButtonFollowStyle }; enum LayoutDirection { diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 4ee17f4..09ba6cc 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -81,7 +81,7 @@ static QString qt_strippedText(QString s) QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false), - menuRole(QAction::TextHeuristicRole), iconVisibleInMenu(-1) + menuRole(QAction::TextHeuristicRole), priority(QAction::NormalPriority), iconVisibleInMenu(-1) { #ifdef QT3_SUPPORT static int qt_static_action_id = -1; @@ -909,6 +909,31 @@ QString QAction::whatsThis() const return d->whatsthis; } +/*! + \property QAction::priority + \since 4.6 + + \brief tells collapsible layouts how the action should be prioritized + + This property can be set to indicate that an action should be prioritied + in a layout. For instance when toolbars have the Qt::ToolButtonTextBesideIcon + mode is set, lower priority actions will hide text labels to preserve space. +*/ +void QAction::setPriority(Priority priority) +{ + Q_D(QAction); + if (d->priority == priority) + return; + + d->priority = priority; + d->sendDataChanged(); +} + +QAction::Priority QAction::priority() const +{ + Q_D(const QAction); + return d->priority; +} /*! \property QAction::checkable diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index 6920ec5..133fab4 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -67,6 +67,7 @@ class Q_GUI_EXPORT QAction : public QObject Q_DECLARE_PRIVATE(QAction) Q_ENUMS(MenuRole) + Q_ENUMS(Priority) Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable) Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) @@ -85,10 +86,14 @@ class Q_GUI_EXPORT QAction : public QObject Q_PROPERTY(bool visible READ isVisible WRITE setVisible) Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole) Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu) + Q_PROPERTY(Priority priority READ priority WRITE setPriority) public: enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, AboutRole, PreferencesRole, QuitRole }; + enum Priority { LowPriority = 0, + NormalPriority = 128, + HighPriority = 256}; explicit QAction(QObject* parent); QAction(const QString &text, QObject* parent); QAction(const QIcon &icon, const QString &text, QObject* parent); @@ -123,6 +128,9 @@ public: void setWhatsThis(const QString &what); QString whatsThis() const; + void setPriority(Priority priority); + Priority priority() const; + #ifndef QT_NO_MENU QMenu *menu() const; void setMenu(QMenu *menu); diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h index bae9bbf..4745ed1 100644 --- a/src/gui/kernel/qaction_p.h +++ b/src/gui/kernel/qaction_p.h @@ -102,6 +102,7 @@ public: uint separator : 1; uint fontSet : 1; QAction::MenuRole menuRole; + QAction::Priority priority; int iconVisibleInMenu : 3; // Only has values -1, 0, and 1 QList widgets; #ifndef QT_NO_GRAPHICSVIEW diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index bccd766..d47c610 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -1865,7 +1865,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_DockWidget_ButtonsHaveFrame Determines if dockwidget buttons should have frames. Default is true. - \value SH_ToolButtonStyle Determines the default system style for tool buttons that uses Qt::ToolButtonSystemDefault. + \value SH_ToolButtonStyle Determines the default system style for tool buttons that uses Qt::ToolButtonFollowStyle. \omitvalue SH_UnderlineAccelerator diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp index 5d0a98a..3901245 100644 --- a/src/gui/widgets/qtoolbutton.cpp +++ b/src/gui/widgets/qtoolbutton.cpp @@ -378,11 +378,17 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const if (d->hasMenu()) option->features |= QStyleOptionToolButton::HasMenu; #endif - if (d->toolButtonStyle == Qt::ToolButtonSystemDefault) { + if (d->toolButtonStyle == Qt::ToolButtonFollowStyle) { option->toolButtonStyle = Qt::ToolButtonStyle(style()->styleHint(QStyle::SH_ToolButtonStyle, option, this)); } else option->toolButtonStyle = d->toolButtonStyle; + if (option->toolButtonStyle == Qt::ToolButtonTextBesideIcon) { + // If the action is not prioritized, remove the text label to save space + if (d->defaultAction && d->defaultAction->priority() < QAction::NormalPriority) + option->toolButtonStyle = Qt::ToolButtonIconOnly; + } + if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) { if (!d->text.isEmpty()) option->toolButtonStyle = Qt::ToolButtonTextOnly; @@ -482,7 +488,7 @@ QSize QToolButton::minimumSizeHint() const If you want your toolbars to depend on system settings, as is possible in GNOME and KDE desktop environments you should - use the ToolButtonSystemDefault. + use the ToolButtonFollowStyle. QToolButton automatically connects this slot to the relevant signal in the QMainWindow in which is resides. diff --git a/tests/auto/qaction/tst_qaction.cpp b/tests/auto/qaction/tst_qaction.cpp index 452ca58..3c71baf 100644 --- a/tests/auto/qaction/tst_qaction.cpp +++ b/tests/auto/qaction/tst_qaction.cpp @@ -105,6 +105,10 @@ void tst_QAction::getSetCheck() obj1.setMenu((QMenu *)0); QCOMPARE((QMenu *)0, obj1.menu()); delete var2; + + QCOMPARE(obj1.priority(), QAction::NormalPriority); + obj1.setPriority(QAction::LowPriority); + QCOMPARE(obj1.priority(), QAction::LowPriority); } class MyWidget : public QWidget diff --git a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/qtoolbutton/tst_qtoolbutton.cpp index 9e342ad..4176507 100644 --- a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp +++ b/tests/auto/qtoolbutton/tst_qtoolbutton.cpp @@ -64,6 +64,7 @@ public: private slots: void getSetCheck(); void triggered(); + void collapseTextOnPriority(); void task230994_iconSize(); void task176137_autoRepeatOfAction(); @@ -160,6 +161,32 @@ void tst_QToolButton::triggered() delete menu; } +void tst_QToolButton::collapseTextOnPriority() +{ + class MyToolButton : public QToolButton + { + friend class tst_QToolButton; + public: + void initStyleOption(QStyleOptionToolButton *option) + { + QToolButton::initStyleOption(option); + } + }; + + MyToolButton button; + button.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + QAction action(button.style()->standardIcon(QStyle::SP_ArrowBack), "test", 0); + button.setDefaultAction(&action); + + QStyleOptionToolButton option; + button.initStyleOption(&option); + QVERIFY(option.toolButtonStyle == Qt::ToolButtonTextBesideIcon); + action.setPriority(QAction::LowPriority); + button.initStyleOption(&option); + QVERIFY(option.toolButtonStyle == Qt::ToolButtonIconOnly); +} + + void tst_QToolButton::task230994_iconSize() { //we check that the iconsize returned bu initStyleOption is valid diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index ae3f7bc..7926020 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -93,7 +93,7 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) , m_qtDocInstaller(0) , m_connectedInitSignals(false) { - setToolButtonStyle(Qt::ToolButtonSystemDefault); + setToolButtonStyle(Qt::ToolButtonFollowStyle); if (usesDefaultCollection()) { MainWindow::collectionFileDirectory(true); @@ -431,6 +431,7 @@ void MainWindow::setupActions() SLOT(printPreview())); m_printAction = menu->addAction(tr("&Print..."), m_centralWidget, SLOT(print())); + m_printAction->setPriority(QAction::LowPriority); m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); m_printAction->setShortcut(QKeySequence::Print); @@ -450,6 +451,7 @@ void MainWindow::setupActions() menu = menuBar()->addMenu(tr("&Edit")); m_copyAction = menu->addAction(tr("&Copy selected Text"), m_centralWidget, SLOT(copySelection())); + m_copyAction->setPriority(QAction::LowPriority); m_copyAction->setIconText("&Copy"); m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); m_copyAction->setShortcuts(QKeySequence::Copy); @@ -476,16 +478,19 @@ void MainWindow::setupActions() m_viewMenu = menuBar()->addMenu(tr("&View")); m_zoomInAction = m_viewMenu->addAction(tr("Zoom &in"), m_centralWidget, SLOT(zoomIn())); + m_zoomInAction->setPriority(QAction::LowPriority); m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); m_zoomInAction->setShortcut(QKeySequence::ZoomIn); m_zoomOutAction = m_viewMenu->addAction(tr("Zoom &out"), m_centralWidget, SLOT(zoomOut())); + m_zoomOutAction->setPriority(QAction::LowPriority); m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"), m_centralWidget, SLOT(resetZoom())); + m_resetZoomAction->setPriority(QAction::LowPriority); m_resetZoomAction->setIcon(QIcon(resourcePath + QLatin1String("/resetzoom.png"))); m_resetZoomAction->setShortcut(tr("Ctrl+0")); @@ -511,6 +516,7 @@ void MainWindow::setupActions() m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); m_nextAction = menu->addAction(tr("&Forward"), m_centralWidget, SLOT(forward())); + m_nextAction->setPriority(QAction::LowPriority); m_nextAction->setEnabled(false); m_nextAction->setShortcuts(QKeySequence::Forward); m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); -- cgit v0.12 From 13254da6c3192937812983f44ce95fe8e1bc602c Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 17 Jul 2009 15:40:49 +0200 Subject: Implement QDesktopWidget::screenCountChanged signal on desktop platforms, and add manual testcase. Provide replacement "screenCount" for numScreens and document numScreens as obsolete to be more consistent with other APIs. --- dist/changes-4.6.0 | 4 + doc/src/qdesktopwidget.qdoc | 83 ++++++----- src/gui/kernel/qapplication_x11.cpp | 13 +- src/gui/kernel/qdesktopwidget.h | 4 + src/gui/kernel/qdesktopwidget_mac.mm | 64 +++++---- src/gui/kernel/qdesktopwidget_mac_p.h | 3 +- src/gui/kernel/qdesktopwidget_win.cpp | 18 +-- src/gui/kernel/qdesktopwidget_x11.cpp | 25 ++++ tests/manual/qdesktopwidget/main.cpp | 188 +++++++++++++++++++++++++ tests/manual/qdesktopwidget/qdesktopwidget.pro | 2 + 10 files changed, 323 insertions(+), 81 deletions(-) create mode 100644 tests/manual/qdesktopwidget/main.cpp create mode 100644 tests/manual/qdesktopwidget/qdesktopwidget.pro diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index 4c7bf52..5e211ff 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -68,3 +68,7 @@ information about a particular change. to the item's position and transformation, you can set the flag QGraphicsItem::ItemSendsGeometryChanges (which is enabled by default by QGraphicsWidget and QGraphicsProxyWidget). + +- QDesktopWidget on X11 no longer emits the resized(int) signal when screens + are added or removed. This was not done on other platforms. Use the + screenCountChanged signal instead diff --git a/doc/src/qdesktopwidget.qdoc b/doc/src/qdesktopwidget.qdoc index 1158904..383ccfc 100644 --- a/doc/src/qdesktopwidget.qdoc +++ b/doc/src/qdesktopwidget.qdoc @@ -54,9 +54,9 @@ Systems with more than one graphics card and monitor can manage the physical screen space available either as multiple desktops, or as a large virtual desktop, which usually has the size of the bounding - rectangle of all the screens (see isVirtualDesktop()). For an + rectangle of all the screens (see virtualDesktop). For an application, one of the available screens is the primary screen, i.e. - the screen where the main widget resides (see primaryScreen()). All + the screen where the main widget resides (see primaryScreen). All windows opened in the context of the application should be constrained to the boundaries of the primary screen; for example, it would be inconvenient if a dialog box popped up on a different @@ -64,16 +64,16 @@ The QDesktopWidget provides information about the geometry of the available screens with screenGeometry(). The number of screens - available is returned by numScreens(). The screen number that a - particular point or widget is located in is returned by - screenNumber(). + available is returned by screenCount, and the screenCountChanged + signal is emitted when screens are added or removed during runtime. + The screen number that a particular point or widget is located in + is returned by screenNumber(). Widgets provided by Qt use this class, for example, to place tooltips, menus and dialog boxes according to the parent or - application widget. - - Applications can use this class to save window positions, or to place - child widgets on one screen. + application widget. Applications can use this class to save window + positions, or to place child widgets and dialogs on one particular + screen. \img qdesktopwidget.png Managing Multiple Screens @@ -115,30 +115,15 @@ */ /*! - \fn bool QDesktopWidget::isVirtualDesktop() const - - Returns true if the system manages the available screens in a - virtual desktop; otherwise returns false. - - For virtual desktops, screen() will always return the same widget. - The size of the virtual desktop is the size of this desktop - widget. -*/ - -/*! - \fn int QDesktopWidget::primaryScreen() const - - Returns the index of the primary screen. - - \sa numScreens() -*/ - -/*! \fn int QDesktopWidget::numScreens() const - + Returns the number of available screens. + + \obsolete + + This function is deprecated. Use screenCount instead. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -146,13 +131,12 @@ Returns a widget that represents the screen with index \a screen (a value of -1 means the default screen). - If the system uses a virtual desktop, the returned widget will have the geometry of the entire virtual desktop; i.e., bounding every \a screen. - \sa primaryScreen(), numScreens(), isVirtualDesktop() + \sa primaryScreen, screenCount, virtualDesktop */ /*! @@ -216,7 +200,7 @@ Returns the index of the screen that contains the largest part of \a widget, or -1 if the widget not on a screen. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -226,7 +210,7 @@ Returns the index of the screen that contains the \a point, or the screen which is the shortest distance from the \a point. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -245,3 +229,34 @@ This signal is emitted when the work area available on \a screen changes. */ + +/*! + \property QDesktopWidget::screenCount + \brief the number of screens currently available on the system. + + \sa screenCountChanged() +*/ + +/*! + \property QDesktopWidget::primaryScreen + \brief the index of the screen that is configured to be the primary screen + on the system. +*/ + +/*! + \property QDesktopWidget::virtualDesktop + + \brief if the system manages the available screens in a virtual desktop. + + For virtual desktops, screen() will always return the same widget. + The size of the virtual desktop is the size of this desktop + widget. +*/ + +/*! + \fn void QDesktopWidget::screenCountChanged(int newCount) + + This signal is emitted when the number of screens changes to \a newCount. + + \sa screenCount +*/ diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index cc41299..a07ccdd 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -3441,19 +3441,10 @@ int QApplication::x11ProcessEvent(XEvent* event) QSize oldSize(w->size()); w->data->crect.setWidth(DisplayWidth(X11->display, scr)); w->data->crect.setHeight(DisplayHeight(X11->display, scr)); - QVarLengthArray oldSizes(desktop->numScreens()); - for (int i = 0; i < desktop->numScreens(); ++i) - oldSizes[i] = desktop->screenGeometry(i); QResizeEvent e(w->size(), oldSize); QApplication::sendEvent(w, &e); - for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) { - if (oldSizes[i] != desktop->screenGeometry(i)) - emit desktop->resized(i); - } - for (int i = oldSizes.count(); i < desktop->numScreens(); ++i) - emit desktop->resized(i); // added - for (int i = desktop->numScreens(); i < oldSizes.count(); ++i) - emit desktop->resized(i); // removed + if (w != desktop) + QApplication::sendEvent(desktop, &e); } #endif // QT_NO_XRANDR diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h index 470f10a..5ac953c 100644 --- a/src/gui/kernel/qdesktopwidget.h +++ b/src/gui/kernel/qdesktopwidget.h @@ -85,6 +85,7 @@ public: Q_SIGNALS: void resized(int); void workAreaResized(int); + void screenCountChanged(int); protected: void resizeEvent(QResizeEvent *e); @@ -97,6 +98,9 @@ private: friend class QApplicationPrivate; }; +inline int QDesktopWidget::screenCount() const +{ return numScreens(); } + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm index 2489fe4..7dd74da 100644 --- a/src/gui/kernel/qdesktopwidget_mac.mm +++ b/src/gui/kernel/qdesktopwidget_mac.mm @@ -97,15 +97,13 @@ QT_USE_NAMESPACE Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation) QDesktopWidgetImplementation::QDesktopWidgetImplementation() - : appScreen(0), displays(0) + : appScreen(0) { onResize(); } QDesktopWidgetImplementation::~QDesktopWidgetImplementation() { - if (displays) - [displays release]; } QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance() @@ -118,13 +116,7 @@ QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] visibleFrame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return availableRects[screenIndex].toRect(); } QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const @@ -132,22 +124,28 @@ QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] frame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return screenRects[screenIndex].toRect(); } void QDesktopWidgetImplementation::onResize() { - if (displays) - [displays release]; - - displays = [[NSScreen screens] retain]; - screenCount = [displays count]; + QMacCocoaAutoReleasePool pool; + NSArray *displays = [NSScreen screens]; + screenCount = [displays count]; + + screenRects.clear(); + availableRects.clear(); + NSRect primaryRect = [[displays objectAtIndex:0] frame]; + for (int i = 0; iappScreen; QRect frame = widget->frameGeometry(); @@ -216,7 +214,7 @@ int QDesktopWidget::screenNumber(const QWidget *widget) const int QDesktopWidget::screenNumber(const QPoint &point) const { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); int closestScreen = -1; int shortestDistance = INT_MAX; for (int i = 0; i < d->screenCount; ++i) { @@ -232,13 +230,25 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *) { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + + const int oldScreenCount = d->screenCount; + const QVector oldRects(d->screenRects); + const QVector oldWorks(d->availableRects); d->onResize(); - for (int i = 0; i < d->screenCount; ++i) { - emit resized(i); + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->screenRects.at(i)) + emit resized(i); + } + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldWorks.at(i) != d->availableRects.at(i)) + emit workAreaResized(i); } + + if (oldscreencount != d->screenCount) + emit screenCountChanged(d->screenCount); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_mac_p.h b/src/gui/kernel/qdesktopwidget_mac_p.h index 0fdc455..e9d5d9f 100644 --- a/src/gui/kernel/qdesktopwidget_mac_p.h +++ b/src/gui/kernel/qdesktopwidget_mac_p.h @@ -64,7 +64,8 @@ public: int appScreen; int screenCount; - NSArray *displays; + QVector availableRects; + QVector screenRects; QRect availableRect(int screenIndex) const; QRect screenRect(int screenIndex) const; diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index fb176b7..a89e08f 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -354,10 +354,8 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *) { Q_D(QDesktopWidget); - QVector oldrects; - oldrects = *d->rects; - QVector oldworkrects; - oldworkrects = *d->workrects; + const QVector oldrects(*d->rects); + const QVector oldworkrects(*d->workrects); int oldscreencount = d->screenCount; QDesktopWidgetPrivate::cleanup(); @@ -368,18 +366,22 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) #endif for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { - QRect oldrect = oldrects[i]; - QRect newrect = d->rects->at(i); + const QRect oldrect = oldrects[i]; + const QRect newrect = d->rects->at(i); if (oldrect != newrect) emit resized(i); } for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { - QRect oldrect = oldworkrects[j]; - QRect newrect = d->workrects->at(j); + const QRect oldrect = oldworkrects[j]; + const QRect newrect = d->workrects->at(j); if (oldrect != newrect) emit workAreaResized(j); } + + if (oldscreencount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } } #ifdef Q_CC_MSVC diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp index 59d3239..1555fc0 100644 --- a/src/gui/kernel/qdesktopwidget_x11.cpp +++ b/src/gui/kernel/qdesktopwidget_x11.cpp @@ -372,7 +372,32 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *event) { Q_D(QDesktopWidget); + int oldScreenCount = d->screenCount; + QVector oldRects(oldScreenCount); + QVector oldWorks(oldScreenCount); + for (int i = 0; i < oldScreenCount; ++i) { + oldRects[i] = d->rects[i]; + oldWorks[i] = d->workareas[i]; + } + d->init(); + + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->rects[i]) + emit resized(i); + } + + // ### workareas are just reset by init, not filled with new values + // ### so this will not work correctly + for (int j = 0; j < qMin(oldScreenCount, d->screenCount); ++j) { + if (oldWorks.at(j) != d->workareas[j]) + emit workAreaResized(j); + } + + if (oldScreenCount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } + qt_desktopwidget_workarea_dirty = true; QWidget::resizeEvent(event); } diff --git a/tests/manual/qdesktopwidget/main.cpp b/tests/manual/qdesktopwidget/main.cpp new file mode 100644 index 0000000..1afc82e --- /dev/null +++ b/tests/manual/qdesktopwidget/main.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +class DesktopView : public QGraphicsView +{ + Q_OBJECT +public: + DesktopView() + : that(0) + { + scene = new QGraphicsScene; + setScene(scene); + + QDesktopWidget *desktop = QApplication::desktop(); + connect(desktop, SIGNAL(resized(int)), this, SLOT(updateScene())); + connect(desktop, SIGNAL(workAreaResized(int)), this, SLOT(updateScene())); + connect(desktop, SIGNAL(screenCountChanged(int)), this, SLOT(updateScene())); + + updateScene(); + + QTransform transform; + transform.scale(0.25, 0.25); + setTransform(transform); + + setBackgroundBrush(Qt::darkGray); + } + +protected: + void moveEvent(QMoveEvent *e) + { + if (that) { + that->setRect(appRect()); + scene->update(); + } + QGraphicsView::moveEvent(e); + } + void resizeEvent(QResizeEvent *e) + { + if (that) { + that->setRect(appRect()); + } + QGraphicsView::resizeEvent(e); + } + +private slots: + void updateScene() + { + scene->clear(); + + const QDesktopWidget *desktop = QApplication::desktop(); + const bool isVirtualDesktop = desktop->isVirtualDesktop(); + const int homeScreen = desktop->screenNumber(this); + + QRect sceneRect; + int screenCount = desktop->screenCount(); + for (int s = 0; s < screenCount; ++s) { + const bool isPrimary = desktop->primaryScreen() == s; + const QRect screenRect = desktop->screenGeometry(s); + const QRect workRect = desktop->availableGeometry(s); + const QBrush fillBrush = palette().brush(isPrimary ? QPalette::Active : QPalette::Inactive, QPalette::Highlight); + QGraphicsRectItem *screen = new QGraphicsRectItem(0, 0, screenRect.width(), screenRect.height()); + + if (isVirtualDesktop) { + thatRoot = QPoint(); + screen->setPos(screenRect.x(), screenRect.y()); + } else { + // for non-virtual desktops we assume that screens are + // simply next to each other + if (s) + screen->setPos(sceneRect.right(), 0); + if (s == homeScreen) + thatRoot = screen->pos().toPoint(); + } + + screen->setBrush(fillBrush); + scene->addItem(screen); + sceneRect.setLeft(qMin(sceneRect.left(), screenRect.left())); + sceneRect.setRight(qMax(sceneRect.right(), screenRect.right())); + sceneRect.setTop(qMin(sceneRect.top(), screenRect.top())); + sceneRect.setBottom(qMax(sceneRect.bottom(), screenRect.bottom())); + + QGraphicsRectItem *workArea = new QGraphicsRectItem(screen); + workArea->setRect(0, 0, workRect.width(), workRect.height()); + workArea->setPos(workRect.x() - screenRect.x(), workRect.y() - screenRect.y()); + workArea->setBrush(Qt::white); + + QGraphicsSimpleTextItem *screenNumber = new QGraphicsSimpleTextItem(workArea); + screenNumber->setText(QString::number(s)); + screenNumber->setPen(QPen(Qt::black, 1)); + screenNumber->setBrush(fillBrush); + screenNumber->setFont(QFont("Arial Black", 18)); + screenNumber->setTransform(QTransform().scale(10, 10)); + screenNumber->setTransformOrigin(screenNumber->boundingRect().center()); + QSizeF center = (workRect.size() - screenNumber->boundingRect().size()) / 2; + screenNumber->setPos(center.width(), center.height()); + + screen->show(); + screen->setZValue(1); + } + + if (isVirtualDesktop) { + QGraphicsRectItem *virtualDesktop = new QGraphicsRectItem; + virtualDesktop->setRect(sceneRect); + virtualDesktop->setPen(QPen(Qt::black)); + virtualDesktop->setBrush(Qt::DiagCrossPattern); + scene->addItem(virtualDesktop); + virtualDesktop->setZValue(-1); + virtualDesktop->show(); + } + + that = new QGraphicsRectItem; + that->setBrush(Qt::red); + that->setOpacity(0.5); + that->setZValue(2); + that->setRect(appRect()); + that->show(); + scene->addItem(that); + + scene->setSceneRect(sceneRect); + scene->update(); + } + + QRect appRect() const + { + QRect rect = frameGeometry(); + if (!QApplication::desktop()->isVirtualDesktop()) { + rect.translate(thatRoot); + } + return rect; + } + +private: + QGraphicsScene *scene; + QGraphicsRectItem *that; + QPoint thatRoot; +}; + +#include "main.moc" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + DesktopView view; + view.show(); + + return app.exec(); +} diff --git a/tests/manual/qdesktopwidget/qdesktopwidget.pro b/tests/manual/qdesktopwidget/qdesktopwidget.pro new file mode 100644 index 0000000..93d56eb --- /dev/null +++ b/tests/manual/qdesktopwidget/qdesktopwidget.pro @@ -0,0 +1,2 @@ +TEMPLATE = app +SOURCES += main.cpp -- cgit v0.12 From 154b98ce283b3ff2d5cad26578ab22dda7af9c81 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 17 Jul 2009 15:58:13 +0200 Subject: Implement QDesktopWidget::screenCount as a property, and add Q_PROPERTY for other attributes as well. --- src/gui/kernel/qdesktopwidget.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h index 5ac953c..a21ae9d 100644 --- a/src/gui/kernel/qdesktopwidget.h +++ b/src/gui/kernel/qdesktopwidget.h @@ -56,6 +56,9 @@ class QDesktopWidgetPrivate; class Q_GUI_EXPORT QDesktopWidget : public QWidget { Q_OBJECT + Q_PROPERTY(bool virtualDesktop READ isVirtualDesktop) + Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged) + Q_PROPERTY(int primaryScreen READ primaryScreen) public: QDesktopWidget(); ~QDesktopWidget(); @@ -63,6 +66,7 @@ public: bool isVirtualDesktop() const; int numScreens() const; + int screenCount() const; int primaryScreen() const; int screenNumber(const QWidget *widget = 0) const; -- cgit v0.12 From 873e502c15e7447626a470f6bf89bf697e7161fb Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Fri, 17 Jul 2009 15:59:22 +0200 Subject: Fix compile --- demos/textedit/textedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/textedit/textedit.cpp b/demos/textedit/textedit.cpp index 7f8e1fe..d1e12bb 100644 --- a/demos/textedit/textedit.cpp +++ b/demos/textedit/textedit.cpp @@ -75,7 +75,7 @@ const QString rsrcPath = ":/images/win"; TextEdit::TextEdit(QWidget *parent) : QMainWindow(parent) { - setToolButtonStyle(Qt::ToolButtonSystemDefault); + setToolButtonStyle(Qt::ToolButtonFollowStyle); setupFileActions(); setupEditActions(); setupTextActions(); -- cgit v0.12 From 7febf8c3eb21e5681b71910fcd08b2933ba82464 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 17 Jul 2009 16:41:50 +0200 Subject: Fix compilation on Mac. --- src/gui/kernel/qdesktopwidget_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm index 11aa7cf..705387d 100644 --- a/src/gui/kernel/qdesktopwidget_mac.mm +++ b/src/gui/kernel/qdesktopwidget_mac.mm @@ -247,7 +247,7 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) emit workAreaResized(i); } - if (oldscreencount != d->screenCount) + if (oldScreenCount != d->screenCount) emit screenCountChanged(d->screenCount); } -- cgit v0.12