summaryrefslogtreecommitdiffstats
path: root/src/network/access/qnetworkreply.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access/qnetworkreply.cpp')
-rw-r--r--src/network/access/qnetworkreply.cpp795
1 files changed, 795 insertions, 0 deletions
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
new file mode 100644
index 0000000000..c176dde669
--- /dev/null
+++ b/src/network/access/qnetworkreply.cpp
@@ -0,0 +1,795 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkreply.h"
+#include "qnetworkreply_p.h"
+#include <QtNetwork/qsslconfiguration.h>
+
+QT_BEGIN_NAMESPACE
+
+QNetworkReplyPrivate::QNetworkReplyPrivate()
+ : readBufferMaxSize(0),
+ operation(QNetworkAccessManager::UnknownOperation),
+ errorCode(QNetworkReply::NoError)
+ , isFinished(false)
+{
+ // set the default attribute values
+ attributes.insert(QNetworkRequest::ConnectionEncryptedAttribute, false);
+}
+
+
+/*!
+ \class QNetworkReply
+ \since 4.4
+ \brief The QNetworkReply class contains the data and headers for a request
+ sent with QNetworkAccessManager
+
+ \reentrant
+ \ingroup network
+ \inmodule QtNetwork
+
+ The QNetworkReply class contains the data and meta data related to
+ a request posted with QNetworkAccessManager. Like QNetworkRequest,
+ it contains a URL and headers (both in parsed and raw form), some
+ information about the reply's state and the contents of the reply
+ itself.
+
+ QNetworkReply is a sequential-access QIODevice, which means that
+ once data is read from the object, it no longer kept by the
+ device. It is therefore the application's responsibility to keep
+ this data if it needs to. Whenever more data is received from the
+ network and processed, the readyRead() signal is emitted.
+
+ The downloadProgress() signal is also emitted when data is
+ received, but the number of bytes contained in it may not
+ represent the actual bytes received, if any transformation is done
+ to the contents (for example, decompressing and removing the
+ protocol overhead).
+
+ Even though QNetworkReply is a QIODevice connected to the contents
+ of the reply, it also emits the uploadProgress() signal, which
+ indicates the progress of the upload for operations that have such
+ content.
+
+ \note Do not delete the object in the slot connected to the
+ error() or finished() signal. Use deleteLater().
+
+ \sa QNetworkRequest, QNetworkAccessManager
+*/
+
+/*!
+ \enum QNetworkReply::NetworkError
+
+ Indicates all possible error conditions found during the
+ processing of the request.
+
+ \value NoError no error condition.
+ \note When the HTTP protocol returns a redirect no error will be
+ reported. You can check if there is a redirect with the
+ QNetworkRequest::RedirectionTargetAttribute attribute.
+
+ \value ConnectionRefusedError the remote server refused the
+ connection (the server is not accepting requests)
+
+ \value RemoteHostClosedError the remote server closed the
+ connection prematurely, before the entire reply was received and
+ processed
+
+ \value HostNotFoundError the remote host name was not found
+ (invalid hostname)
+
+ \value TimeoutError the connection to the remote server
+ timed out
+
+ \value OperationCanceledError the operation was canceled via calls
+ to abort() or close() before it was finished.
+
+ \value SslHandshakeFailedError the SSL/TLS handshake failed and the
+ encrypted channel could not be established. The sslErrors() signal
+ should have been emitted.
+
+ \value TemporaryNetworkFailureError the connection was broken due
+ to disconnection from the network, however the system has initiated
+ roaming to another access point. The request should be resubmitted
+ and will be processed as soon as the connection is re-established.
+
+ \value ProxyConnectionRefusedError the connection to the proxy
+ server was refused (the proxy server is not accepting requests)
+
+ \value ProxyConnectionClosedError the proxy server closed the
+ connection prematurely, before the entire reply was received and
+ processed
+
+ \value ProxyNotFoundError the proxy host name was not
+ found (invalid proxy hostname)
+
+ \value ProxyTimeoutError the connection to the proxy
+ timed out or the proxy did not reply in time to the request sent
+
+ \value ProxyAuthenticationRequiredError the proxy requires
+ authentication in order to honour the request but did not accept
+ any credentials offered (if any)
+
+ \value ContentAccessDenied the access to the remote
+ content was denied (similar to HTTP error 401)
+
+ \value ContentOperationNotPermittedError the operation requested
+ on the remote content is not permitted
+
+ \value ContentNotFoundError the remote content was not
+ found at the server (similar to HTTP error 404)
+
+ \value AuthenticationRequiredError the remote server requires
+ authentication to serve the content but the credentials provided
+ were not accepted (if any)
+
+ \value ContentReSendError the request needed to be sent
+ again, but this failed for example because the upload data
+ could not be read a second time.
+
+ \value ProtocolUnknownError the Network Access API cannot
+ honor the request because the protocol is not known
+
+ \value ProtocolInvalidOperationError the requested operation is
+ invalid for this protocol
+
+ \value UnknownNetworkError an unknown network-related
+ error was detected
+
+ \value UnknownProxyError an unknown proxy-related error
+ was detected
+
+ \value UnknownContentError an unknown error related to
+ the remote content was detected
+
+ \value ProtocolFailure a breakdown in protocol was
+ detected (parsing error, invalid or unexpected responses, etc.)
+
+ \sa error()
+*/
+
+/*!
+ \fn void QNetworkReply::sslErrors(const QList<QSslError> &errors)
+
+ This signal is emitted if the SSL/TLS session encountered errors
+ during the set up, including certificate verification errors. The
+ \a errors parameter contains the list of errors.
+
+ To indicate that the errors are not fatal and that the connection
+ should proceed, the ignoreSslErrors() function should be called
+ from the slot connected to this signal. If it is not called, the
+ SSL session will be torn down before any data is exchanged
+ (including the URL).
+
+ This signal can be used to display an error message to the user
+ indicating that security may be compromised and display the
+ SSL settings (see sslConfiguration() to obtain it). If the user
+ decides to proceed after analyzing the remote certificate, the
+ slot should call ignoreSslErrors().
+
+ \sa QSslSocket::sslErrors(), QNetworkAccessManager::sslErrors(),
+ sslConfiguration(), ignoreSslErrors()
+*/
+
+/*!
+ \fn void QNetworkReply::metaDataChanged()
+
+ \omit FIXME: Update name? \endomit
+
+ This signal is emitted whenever the metadata in this reply
+ changes. metadata is any information that is not the content
+ (data) itself, including the network headers. In the majority of
+ cases, the metadata will be known fully by the time the first
+ byte of data is received. However, it is possible to receive
+ updates of headers or other metadata during the processing of the
+ data.
+
+ \sa header(), rawHeaderList(), rawHeader(), hasRawHeader()
+*/
+
+/*!
+ \fn void QNetworkReply::finished()
+
+ This signal is emitted when the reply has finished
+ processing. After this signal is emitted, there will be no more
+ updates to the reply's data or metadata.
+
+ Unless close() has been called, the reply will be still be opened
+ for reading, so the data can be retrieved by calls to read() or
+ readAll(). In particular, if no calls to read() were made as a
+ result of readyRead(), a call to readAll() will retrieve the full
+ contents in a QByteArray.
+
+ This signal is emitted in tandem with
+ QNetworkAccessManager::finished() where that signal's reply
+ parameter is this object.
+
+ \note Do not delete the object in the slot connected to this
+ signal. Use deleteLater().
+
+ You can also use isFinished() to check if a QNetworkReply
+ has finished even before you receive the finished() signal.
+
+ \sa QNetworkAccessManager::finished(), isFinished()
+*/
+
+/*!
+ \fn void QNetworkReply::error(QNetworkReply::NetworkError code)
+
+ This signal is emitted when the reply detects an error in
+ processing. The finished() signal will probably follow, indicating
+ that the connection is over.
+
+ The \a code parameter contains the code of the error that was
+ detected. Call errorString() to obtain a textual representation of
+ the error condition.
+
+ \note Do not delete the object in the slot connected to this
+ signal. Use deleteLater().
+
+ \sa error(), errorString()
+*/
+
+/*!
+ \fn void QNetworkReply::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
+
+ This signal is emitted to indicate the progress of the upload part
+ of this network request, if there's any. If there's no upload
+ associated with this request, this signal will not be emitted.
+
+ The \a bytesSent
+ parameter indicates the number of bytes uploaded, while \a
+ bytesTotal indicates the total number of bytes to be uploaded. If
+ the number of bytes to be uploaded could not be determined, \a
+ bytesTotal will be -1.
+
+ The upload is finished when \a bytesSent is equal to \a
+ bytesTotal. At that time, \a bytesTotal will not be -1.
+
+ \sa downloadProgress()
+*/
+
+/*!
+ \fn void QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+
+ This signal is emitted to indicate the progress of the download
+ part of this network request, if there's any. If there's no
+ download associated with this request, this signal will be emitted
+ once with 0 as the value of both \a bytesReceived and \a
+ bytesTotal.
+
+ The \a bytesReceived parameter indicates the number of bytes
+ received, while \a bytesTotal indicates the total number of bytes
+ expected to be downloaded. If the number of bytes to be downloaded
+ is not known, \a bytesTotal will be -1.
+
+ The download is finished when \a bytesReceived is equal to \a
+ bytesTotal. At that time, \a bytesTotal will not be -1.
+
+ Note that the values of both \a bytesReceived and \a bytesTotal
+ may be different from size(), the total number of bytes
+ obtained through read() or readAll(), or the value of the
+ header(ContentLengthHeader). The reason for that is that there may
+ be protocol overhead or the data may be compressed during the
+ download.
+
+ \sa uploadProgress(), bytesAvailable()
+*/
+
+/*!
+ \fn void QNetworkReply::abort()
+
+ Aborts the operation immediately and close down any network
+ connections still open. Uploads still in progress are also
+ aborted.
+
+ \sa close()
+*/
+
+/*!
+ Creates a QNetworkReply object with parent \a parent.
+
+ You cannot directly instantiate QNetworkReply objects. Use
+ QNetworkAccessManager functions to do that.
+*/
+QNetworkReply::QNetworkReply(QObject *parent)
+ : QIODevice(*new QNetworkReplyPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
+ : QIODevice(dd, parent)
+{
+}
+
+/*!
+ Disposes of this reply and frees any resources associated with
+ it. If any network connections are still open, they will be
+ closed.
+
+ \sa abort(), close()
+*/
+QNetworkReply::~QNetworkReply()
+{
+}
+
+/*!
+ Closes this device for reading. Unread data is discarded, but the
+ network resources are not discarded until they are finished. In
+ particular, if any upload is in progress, it will continue until
+ it is done.
+
+ The finished() signal is emitted when all operations are over and
+ the network resources are freed.
+
+ \sa abort(), finished()
+*/
+void QNetworkReply::close()
+{
+ QIODevice::close();
+}
+
+/*!
+ \internal
+*/
+bool QNetworkReply::isSequential() const
+{
+ return true;
+}
+
+/*!
+ Returns the size of the read buffer, in bytes.
+
+ \sa setReadBufferSize()
+*/
+qint64 QNetworkReply::readBufferSize() const
+{
+ return d_func()->readBufferMaxSize;
+}
+
+/*!
+ Sets the size of the read buffer to be \a size bytes. The read
+ buffer is the buffer that holds data that is being downloaded off
+ the network, before it is read with QIODevice::read(). Setting the
+ buffer size to 0 will make the buffer unlimited in size.
+
+ QNetworkReply will try to stop reading from the network once this
+ buffer is full (i.e., bytesAvailable() returns \a size or more),
+ thus causing the download to throttle down as well. If the buffer
+ is not limited in size, QNetworkReply will try to download as fast
+ as possible from the network.
+
+ Unlike QAbstractSocket::setReadBufferSize(), QNetworkReply cannot
+ guarantee precision in the read buffer size. That is,
+ bytesAvailable() can return more than \a size.
+
+ \sa readBufferSize()
+*/
+void QNetworkReply::setReadBufferSize(qint64 size)
+{
+ Q_D(QNetworkReply);
+ d->readBufferMaxSize = size;
+}
+
+/*!
+ Returns the QNetworkAccessManager that was used to create this
+ QNetworkReply object. Initially, it is also the parent object.
+*/
+QNetworkAccessManager *QNetworkReply::manager() const
+{
+ return d_func()->manager;
+}
+
+/*!
+ Returns the request that was posted for this reply. In special,
+ note that the URL for the request may be different than that of
+ the reply.
+
+ \sa QNetworkRequest::url(), url(), setRequest()
+*/
+QNetworkRequest QNetworkReply::request() const
+{
+ return d_func()->request;
+}
+
+/*!
+ Returns the operation that was posted for this reply.
+
+ \sa setOperation()
+*/
+QNetworkAccessManager::Operation QNetworkReply::operation() const
+{
+ return d_func()->operation;
+}
+
+/*!
+ Returns the error that was found during the processing of this
+ request. If no error was found, returns NoError.
+
+ \sa setError()
+*/
+QNetworkReply::NetworkError QNetworkReply::error() const
+{
+ return d_func()->errorCode;
+}
+
+/*!
+ \since 4.6
+
+ Returns true when the reply has finished or was aborted.
+
+ \sa isRunning()
+*/
+bool QNetworkReply::isFinished() const
+{
+ return d_func()->isFinished;
+}
+
+/*!
+ \since 4.6
+
+ Returns true when the request is still processing and the
+ reply has not finished or was aborted yet.
+
+ \sa isFinished()
+*/
+bool QNetworkReply::isRunning() const
+{
+ return !isFinished();
+}
+
+/*!
+ Returns the URL of the content downloaded or uploaded. Note that
+ the URL may be different from that of the original request.
+
+ \sa request(), setUrl(), QNetworkRequest::url()
+*/
+QUrl QNetworkReply::url() const
+{
+ return d_func()->url;
+}
+
+/*!
+ Returns the value of the known header \a header, if that header
+ was sent by the remote server. If the header was not sent, returns
+ an invalid QVariant.
+
+ \sa rawHeader(), setHeader(), QNetworkRequest::header()
+*/
+QVariant QNetworkReply::header(QNetworkRequest::KnownHeaders header) const
+{
+ return d_func()->cookedHeaders.value(header);
+}
+
+/*!
+ Returns true if the raw header of name \a headerName was sent by
+ the remote server
+
+ \sa rawHeader()
+*/
+bool QNetworkReply::hasRawHeader(const QByteArray &headerName) const
+{
+ Q_D(const QNetworkReply);
+ return d->findRawHeader(headerName) != d->rawHeaders.constEnd();
+}
+
+/*!
+ Returns the raw contents of the header \a headerName as sent by
+ the remote server. If there is no such header, returns an empty
+ byte array, which may be indistinguishable from an empty
+ header. Use hasRawHeader() to verify if the server sent such
+ header field.
+
+ \sa setRawHeader(), hasRawHeader(), header()
+*/
+QByteArray QNetworkReply::rawHeader(const QByteArray &headerName) const
+{
+ Q_D(const QNetworkReply);
+ QNetworkHeadersPrivate::RawHeadersList::ConstIterator it =
+ d->findRawHeader(headerName);
+ if (it != d->rawHeaders.constEnd())
+ return it->second;
+ return QByteArray();
+}
+
+/*! \typedef QNetworkReply::RawHeaderPair
+
+ RawHeaderPair is a QPair<QByteArray, QByteArray> where the first
+ QByteArray is the header name and the second is the header.
+ */
+
+/*!
+ Returns a list of raw header pairs.
+ */
+const QList<QNetworkReply::RawHeaderPair>& QNetworkReply::rawHeaderPairs() const
+{
+ Q_D(const QNetworkReply);
+ return d->rawHeaders;
+}
+
+/*!
+ Returns a list of headers fields that were sent by the remote
+ server, in the order that they were sent. Duplicate headers are
+ merged together and take place of the latter duplicate.
+*/
+QList<QByteArray> QNetworkReply::rawHeaderList() const
+{
+ return d_func()->rawHeadersKeys();
+}
+
+/*!
+ Returns the attribute associated with the code \a code. If the
+ attribute has not been set, it returns an invalid QVariant (type QVariant::Null).
+
+ You can expect the default values listed in
+ QNetworkRequest::Attribute to be applied to the values returned by
+ this function.
+
+ \sa setAttribute(), QNetworkRequest::Attribute
+*/
+QVariant QNetworkReply::attribute(QNetworkRequest::Attribute code) const
+{
+ return d_func()->attributes.value(code);
+}
+
+#ifndef QT_NO_OPENSSL
+/*!
+ Returns the SSL configuration and state associated with this
+ reply, if SSL was used. It will contain the remote server's
+ certificate, its certificate chain leading to the Certificate
+ Authority as well as the encryption ciphers in use.
+
+ The peer's certificate and its certificate chain will be known by
+ the time sslErrors() is emitted, if it's emitted.
+*/
+QSslConfiguration QNetworkReply::sslConfiguration() const
+{
+ QSslConfiguration config;
+
+ // determine if we support this extension
+ int id = metaObject()->indexOfMethod("sslConfigurationImplementation()");
+ if (id != -1) {
+ void *arr[] = { &config, 0 };
+ const_cast<QNetworkReply *>(this)->qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
+ }
+ return config;
+}
+
+/*!
+ Sets the SSL configuration for the network connection associated
+ with this request, if possible, to be that of \a config.
+*/
+void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
+{
+ if (config.isNull())
+ return;
+
+ int id = metaObject()->indexOfMethod("setSslConfigurationImplementation(QSslConfiguration)");
+ if (id != -1) {
+ QSslConfiguration copy(config);
+ void *arr[] = { 0, &copy };
+ qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
+ }
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ If this function is called, the SSL errors given in \a errors
+ will be ignored.
+
+ Note that you can set the expected certificate in the SSL error:
+ If, for instance, you want to issue a request to a server that uses
+ a self-signed certificate, consider the following snippet:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkreply.cpp 0
+
+ Multiple calls to this function will replace the list of errors that
+ were passed in previous calls.
+ You can clear the list of errors you want to ignore by calling this
+ function with an empty list.
+
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
+*/
+void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ // do this cryptic trick, because we could not add a virtual method to this class later on
+ // since that breaks binary compatibility
+ int id = metaObject()->indexOfMethod("ignoreSslErrorsImplementation(QList<QSslError>)");
+ if (id != -1) {
+ QList<QSslError> copy(errors);
+ void *arr[] = { 0, &copy };
+ qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
+ }
+}
+#endif
+
+/*!
+ If this function is called, SSL errors related to network
+ connection will be ignored, including certificate validation
+ errors.
+
+ Note that calling this function without restraint may pose a
+ security risk for your application. Use it with care.
+
+ This function can be called from the slot connected to the
+ sslErrors() signal, which indicates which errors were
+ found.
+
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
+*/
+void QNetworkReply::ignoreSslErrors()
+{
+}
+
+/*!
+ \internal
+*/
+qint64 QNetworkReply::writeData(const char *, qint64)
+{
+ return -1; // you can't write
+}
+
+/*!
+ Sets the associated operation for this object to be \a
+ operation. This value will be returned by operation().
+
+ Note: the operation should be set when this object is created and
+ not changed again.
+
+ \sa operation(), setRequest()
+*/
+void QNetworkReply::setOperation(QNetworkAccessManager::Operation operation)
+{
+ Q_D(QNetworkReply);
+ d->operation = operation;
+}
+
+/*!
+ Sets the associated request for this object to be \a request. This
+ value will be returned by request().
+
+ Note: the request should be set when this object is created and
+ not changed again.
+
+ \sa request(), setOperation()
+*/
+void QNetworkReply::setRequest(const QNetworkRequest &request)
+{
+ Q_D(QNetworkReply);
+ d->request = request;
+}
+
+/*!
+ Sets the error condition to be \a errorCode. The human-readable
+ message is set with \a errorString.
+
+ Calling setError() does not emit the error(QNetworkReply::NetworkError)
+ signal.
+
+ \sa error(), errorString()
+*/
+void QNetworkReply::setError(NetworkError errorCode, const QString &errorString)
+{
+ Q_D(QNetworkReply);
+ d->errorCode = errorCode;
+ setErrorString(errorString); // in QIODevice
+}
+
+/*!
+ \since 4.8
+ Sets the reply as \a finished.
+
+ After having this set the replies data must not change.
+
+ \sa isFinished()
+*/
+void QNetworkReply::setFinished(bool finished)
+{
+ Q_D(QNetworkReply);
+ d->isFinished = finished;
+}
+
+
+/*!
+ Sets the URL being processed to be \a url. Normally, the URL
+ matches that of the request that was posted, but for a variety of
+ reasons it can be different (for example, a file path being made
+ absolute or canonical).
+
+ \sa url(), request(), QNetworkRequest::url()
+*/
+void QNetworkReply::setUrl(const QUrl &url)
+{
+ Q_D(QNetworkReply);
+ d->url = url;
+}
+
+/*!
+ Sets the known header \a header to be of value \a value. The
+ corresponding raw form of the header will be set as well.
+
+ \sa header(), setRawHeader(), QNetworkRequest::setHeader()
+*/
+void QNetworkReply::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
+{
+ Q_D(QNetworkReply);
+ d->setCookedHeader(header, value);
+}
+
+/*!
+ Sets the raw header \a headerName to be of value \a value. If \a
+ headerName was previously set, it is overridden. Multiple HTTP
+ headers of the same name are functionally equivalent to one single
+ header with the values concatenated, separated by commas.
+
+ If \a headerName matches a known header, the value \a value will
+ be parsed and the corresponding parsed form will also be set.
+
+ \sa rawHeader(), header(), setHeader(), QNetworkRequest::setRawHeader()
+*/
+void QNetworkReply::setRawHeader(const QByteArray &headerName, const QByteArray &value)
+{
+ Q_D(QNetworkReply);
+ d->setRawHeader(headerName, value);
+}
+
+/*!
+ Sets the attribute \a code to have value \a value. If \a code was
+ previously set, it will be overridden. If \a value is an invalid
+ QVariant, the attribute will be unset.
+
+ \sa attribute(), QNetworkRequest::setAttribute()
+*/
+void QNetworkReply::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
+{
+ Q_D(QNetworkReply);
+ if (value.isValid())
+ d->attributes.insert(code, value);
+ else
+ d->attributes.remove(code);
+}
+
+QT_END_NAMESPACE