summaryrefslogtreecommitdiffstats
path: root/src/multimediakit/video/qvideosurfaceformat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimediakit/video/qvideosurfaceformat.cpp')
-rw-r--r--src/multimediakit/video/qvideosurfaceformat.cpp709
1 files changed, 709 insertions, 0 deletions
diff --git a/src/multimediakit/video/qvideosurfaceformat.cpp b/src/multimediakit/video/qvideosurfaceformat.cpp
new file mode 100644
index 000000000..58b2baa44
--- /dev/null
+++ b/src/multimediakit/video/qvideosurfaceformat.cpp
@@ -0,0 +1,709 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideosurfaceformat.h"
+
+#include <qdebug.h>
+#include <qmetatype.h>
+#include <qpair.h>
+#include <qvariant.h>
+#include <qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfaceFormatPrivate : public QSharedData
+{
+public:
+ QVideoSurfaceFormatPrivate()
+ : pixelFormat(QVideoFrame::Format_Invalid)
+ , handleType(QAbstractVideoBuffer::NoHandle)
+ , scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , pixelAspectRatio(1, 1)
+ , ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
+ , frameRate(0.0)
+ {
+ }
+
+ QVideoSurfaceFormatPrivate(
+ const QSize &size,
+ QVideoFrame::PixelFormat format,
+ QAbstractVideoBuffer::HandleType type)
+ : pixelFormat(format)
+ , handleType(type)
+ , scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , frameSize(size)
+ , pixelAspectRatio(1, 1)
+ , ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
+ , viewport(QPoint(0, 0), size)
+ , frameRate(0.0)
+ {
+ }
+
+ QVideoSurfaceFormatPrivate(const QVideoSurfaceFormatPrivate &other)
+ : QSharedData(other)
+ , pixelFormat(other.pixelFormat)
+ , handleType(other.handleType)
+ , scanLineDirection(other.scanLineDirection)
+ , frameSize(other.frameSize)
+ , pixelAspectRatio(other.pixelAspectRatio)
+ , ycbcrColorSpace(other.ycbcrColorSpace)
+ , viewport(other.viewport)
+ , frameRate(other.frameRate)
+ , propertyNames(other.propertyNames)
+ , propertyValues(other.propertyValues)
+ {
+ }
+
+ bool operator ==(const QVideoSurfaceFormatPrivate &other) const
+ {
+ if (pixelFormat == other.pixelFormat
+ && handleType == other.handleType
+ && scanLineDirection == other.scanLineDirection
+ && frameSize == other.frameSize
+ && pixelAspectRatio == other.pixelAspectRatio
+ && viewport == other.viewport
+ && frameRatesEqual(frameRate, other.frameRate)
+ && ycbcrColorSpace == other.ycbcrColorSpace
+ && propertyNames.count() == other.propertyNames.count()) {
+ for (int i = 0; i < propertyNames.count(); ++i) {
+ int j = other.propertyNames.indexOf(propertyNames.at(i));
+
+ if (j == -1 || propertyValues.at(i) != other.propertyValues.at(j))
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ inline static bool frameRatesEqual(qreal r1, qreal r2)
+ {
+ return qAbs(r1 - r2) <= 0.00001 * qMin(qAbs(r1), qAbs(r2));
+ }
+
+ QVideoFrame::PixelFormat pixelFormat;
+ QAbstractVideoBuffer::HandleType handleType;
+ QVideoSurfaceFormat::Direction scanLineDirection;
+ QSize frameSize;
+ QSize pixelAspectRatio;
+ QVideoSurfaceFormat::YCbCrColorSpace ycbcrColorSpace;
+ QRect viewport;
+ qreal frameRate;
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+};
+
+/*!
+ \class QVideoSurfaceFormat
+ \brief The QVideoSurfaceFormat class specifies the stream format of a video presentation
+ surface.
+ \since 1.0
+ \inmodule QtMultimediaKit
+
+ A video surface presents a stream of video frames. The surface's format describes the type of
+ the frames and determines how they should be presented.
+
+ XXX Why do I care
+ XXX why isn't it videostreamformat then?
+
+ The core properties of a video stream required to setup a video surface are the pixel format
+ given by pixelFormat(), and the frame dimensions given by frameSize().
+
+ If the surface is to present frames using a frame's handle a surface format will also include
+ a handle type which is given by the handleType() function.
+
+ The region of a frame that is actually displayed on a video surface is given by the viewport().
+ A stream may have a viewport less than the entire region of a frame to allow for videos smaller
+ than the nearest optimal size of a video frame. For example the width of a frame may be
+ extended so that the start of each scan line is eight byte aligned.
+
+ Other common properties are the pixelAspectRatio(), scanLineDirection(), and frameRate().
+ Additionally a stream may have some additional type specific properties which are listed by the
+ dynamicPropertyNames() function and can be accessed using the property(), and setProperty()
+ functions.
+*/
+
+/*!
+ \enum QVideoSurfaceFormat::Direction
+
+ Enumerates the layout direction of video scan lines.
+
+ \value TopToBottom Scan lines are arranged from the top of the frame to the bottom.
+ \value BottomToTop Scan lines are arranged from the bottom of the frame to the top.
+*/
+
+/*!
+ \enum QVideoSurfaceFormat::YCbCrColorSpace
+
+ Enumerates the Y'CbCr color space of video frames.
+
+ \value YCbCr_Undefined
+ No color space is specified.
+
+ \value YCbCr_BT601
+ A Y'CbCr color space defined by ITU-R recommendation BT.601
+ with Y value range from 16 to 235, and Cb/Cr range from 16 to 240.
+ Used in standard definition video.
+
+ \value YCbCr_BT709
+ A Y'CbCr color space defined by ITU-R BT.709 with the same values range as YCbCr_BT601. Used
+ for HDTV.
+
+ \value YCbCr_xvYCC601
+ The BT.601 color space with the value range extended to 0 to 255.
+ It is backward compatibile with BT.601 and uses values outside BT.601 range to represent a
+ wider range of colors.
+
+ \value YCbCr_xvYCC709
+ The BT.709 color space with the value range extended to 0 to 255.
+
+ \value YCbCr_JPEG
+ The full range Y'CbCr color space used in JPEG files.
+*/
+
+/*!
+ Constructs a null video stream format.
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat()
+ : d(new QVideoSurfaceFormatPrivate)
+{
+}
+
+/*!
+ Contructs a description of stream which receives stream of \a type buffers with given frame
+ \a size and pixel \a format.
+ \since 1.0
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat(
+ const QSize& size, QVideoFrame::PixelFormat format, QAbstractVideoBuffer::HandleType type)
+ : d(new QVideoSurfaceFormatPrivate(size, format, type))
+{
+}
+
+/*!
+ Constructs a copy of \a other.
+ \since 1.0
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat(const QVideoSurfaceFormat &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Assigns the values of \a other to this object.
+ \since 1.0
+*/
+QVideoSurfaceFormat &QVideoSurfaceFormat::operator =(const QVideoSurfaceFormat &other)
+{
+ d = other.d;
+
+ return *this;
+}
+
+/*!
+ Destroys a video stream description.
+*/
+QVideoSurfaceFormat::~QVideoSurfaceFormat()
+{
+}
+
+/*!
+ Identifies if a video surface format has a valid pixel format and frame size.
+
+ Returns true if the format is valid, and false otherwise.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::isValid() const
+{
+ return d->pixelFormat != QVideoFrame::Format_Invalid && d->frameSize.isValid();
+}
+
+/*!
+ Returns true if \a other is the same as this video format, and false if they are different.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::operator ==(const QVideoSurfaceFormat &other) const
+{
+ return d == other.d || *d == *other.d;
+}
+
+/*!
+ Returns true if \a other is different to a video format, and false if they are the same.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::operator !=(const QVideoSurfaceFormat &other) const
+{
+ return d != other.d && !(*d == *other.d);
+}
+
+/*!
+ Returns the pixel format of frames in a video stream.
+ \since 1.0
+*/
+QVideoFrame::PixelFormat QVideoSurfaceFormat::pixelFormat() const
+{
+ return d->pixelFormat;
+}
+
+/*!
+ Returns the type of handle the surface uses to present the frame data.
+
+ If the handle type is QAbstractVideoBuffer::NoHandle buffers with any handle type are valid
+ provided they can be \l {QAbstractVideoBuffer::map()}{mapped} with the
+ QAbstractVideoBuffer::ReadOnly flag. If the handleType() is not QAbstractVideoBuffer::NoHandle
+ then the handle type of the buffer must be the same as that of the surface format.
+ \since 1.0
+*/
+QAbstractVideoBuffer::HandleType QVideoSurfaceFormat::handleType() const
+{
+ return d->handleType;
+}
+
+/*!
+ Returns the dimensions of frames in a video stream.
+
+ \sa frameWidth(), frameHeight()
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::frameSize() const
+{
+ return d->frameSize;
+}
+
+/*!
+ Returns the width of frames in a video stream.
+
+ \sa frameSize(), frameHeight()
+ \since 1.0
+*/
+int QVideoSurfaceFormat::frameWidth() const
+{
+ return d->frameSize.width();
+}
+
+/*!
+ Returns the height of frame in a video stream.
+ \since 1.0
+*/
+int QVideoSurfaceFormat::frameHeight() const
+{
+ return d->frameSize.height();
+}
+
+/*!
+ Sets the size of frames in a video stream to \a size.
+
+ This will reset the viewport() to fill the entire frame.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameSize(const QSize &size)
+{
+ d->frameSize = size;
+ d->viewport = QRect(QPoint(0, 0), size);
+}
+
+/*!
+ \overload
+
+ Sets the \a width and \a height of frames in a video stream.
+
+ This will reset the viewport() to fill the entire frame.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameSize(int width, int height)
+{
+ d->frameSize = QSize(width, height);
+ d->viewport = QRect(0, 0, width, height);
+}
+
+/*!
+ Returns the viewport of a video stream.
+
+ The viewport is the region of a video frame that is actually displayed.
+
+ By default the viewport covers an entire frame.
+ \since 1.0
+*/
+QRect QVideoSurfaceFormat::viewport() const
+{
+ return d->viewport;
+}
+
+/*!
+ Sets the viewport of a video stream to \a viewport.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setViewport(const QRect &viewport)
+{
+ d->viewport = viewport;
+}
+
+/*!
+ Returns the direction of scan lines.
+ \since 1.0
+*/
+QVideoSurfaceFormat::Direction QVideoSurfaceFormat::scanLineDirection() const
+{
+ return d->scanLineDirection;
+}
+
+/*!
+ Sets the \a direction of scan lines.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setScanLineDirection(Direction direction)
+{
+ d->scanLineDirection = direction;
+}
+
+/*!
+ Returns the frame rate of a video stream in frames per second.
+ \since 1.0
+*/
+qreal QVideoSurfaceFormat::frameRate() const
+{
+ return d->frameRate;
+}
+
+/*!
+ Sets the frame \a rate of a video stream in frames per second.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameRate(qreal rate)
+{
+ d->frameRate = rate;
+}
+
+/*!
+ Returns a video stream's pixel aspect ratio.
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::pixelAspectRatio() const
+{
+ return d->pixelAspectRatio;
+}
+
+/*!
+ Sets a video stream's pixel aspect \a ratio.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setPixelAspectRatio(const QSize &ratio)
+{
+ d->pixelAspectRatio = ratio;
+}
+
+/*!
+ \overload
+
+ Sets the \a horizontal and \a vertical elements of a video stream's pixel aspect ratio.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setPixelAspectRatio(int horizontal, int vertical)
+{
+ d->pixelAspectRatio = QSize(horizontal, vertical);
+}
+
+/*!
+ Returns the Y'CbCr color space of a video stream.
+ \since 1.0
+*/
+QVideoSurfaceFormat::YCbCrColorSpace QVideoSurfaceFormat::yCbCrColorSpace() const
+{
+ return d->ycbcrColorSpace;
+}
+
+/*!
+ Sets the Y'CbCr color \a space of a video stream.
+ It is only used with raw YUV frame types.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setYCbCrColorSpace(QVideoSurfaceFormat::YCbCrColorSpace space)
+{
+ d->ycbcrColorSpace = space;
+}
+
+/*!
+ Returns a suggested size in pixels for the video stream.
+
+ This is the size of the viewport scaled according to the pixel aspect ratio.
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::sizeHint() const
+{
+ QSize size = d->viewport.size();
+
+ if (d->pixelAspectRatio.height() != 0)
+ size.setWidth(size.width() * d->pixelAspectRatio.width() / d->pixelAspectRatio.height());
+
+ return size;
+}
+
+/*!
+ Returns a list of video format dynamic property names.
+ \since 1.0
+*/
+QList<QByteArray> QVideoSurfaceFormat::propertyNames() const
+{
+ return (QList<QByteArray>()
+ << "handleType"
+ << "pixelFormat"
+ << "frameSize"
+ << "frameWidth"
+ << "viewport"
+ << "scanLineDirection"
+ << "frameRate"
+ << "pixelAspectRatio"
+ << "sizeHint"
+ << "yCbCrColorSpace")
+ + d->propertyNames;
+}
+
+/*!
+ Returns the value of the video format's \a name property.
+ \since 1.0
+*/
+QVariant QVideoSurfaceFormat::property(const char *name) const
+{
+ if (qstrcmp(name, "handleType") == 0) {
+ return qVariantFromValue(d->handleType);
+ } else if (qstrcmp(name, "pixelFormat") == 0) {
+ return qVariantFromValue(d->pixelFormat);
+ } else if (qstrcmp(name, "handleType") == 0) {
+ return qVariantFromValue(d->handleType);
+ } else if (qstrcmp(name, "frameSize") == 0) {
+ return d->frameSize;
+ } else if (qstrcmp(name, "frameWidth") == 0) {
+ return d->frameSize.width();
+ } else if (qstrcmp(name, "frameHeight") == 0) {
+ return d->frameSize.height();
+ } else if (qstrcmp(name, "viewport") == 0) {
+ return d->viewport;
+ } else if (qstrcmp(name, "scanLineDirection") == 0) {
+ return qVariantFromValue(d->scanLineDirection);
+ } else if (qstrcmp(name, "frameRate") == 0) {
+ return qVariantFromValue(d->frameRate);
+ } else if (qstrcmp(name, "pixelAspectRatio") == 0) {
+ return qVariantFromValue(d->pixelAspectRatio);
+ } else if (qstrcmp(name, "sizeHint") == 0) {
+ return sizeHint();
+ } else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
+ return qVariantFromValue(d->ycbcrColorSpace);
+ } else {
+ int id = 0;
+ for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
+
+ return id < d->propertyValues.count()
+ ? d->propertyValues.at(id)
+ : QVariant();
+ }
+}
+
+/*!
+ Sets the video format's \a name property to \a value.
+
+ Trying to set a read only property will be ignored.
+
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value)
+{
+ if (qstrcmp(name, "handleType") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "pixelFormat") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "frameSize") == 0) {
+ if (qVariantCanConvert<QSize>(value)) {
+ d->frameSize = qvariant_cast<QSize>(value);
+ d->viewport = QRect(QPoint(0, 0), d->frameSize);
+ }
+ } else if (qstrcmp(name, "frameWidth") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "frameHeight") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "viewport") == 0) {
+ if (qVariantCanConvert<QRect>(value))
+ d->viewport = qvariant_cast<QRect>(value);
+ } else if (qstrcmp(name, "scanLineDirection") == 0) {
+ if (qVariantCanConvert<Direction>(value))
+ d->scanLineDirection = qvariant_cast<Direction>(value);
+ } else if (qstrcmp(name, "frameRate") == 0) {
+ if (qVariantCanConvert<qreal>(value))
+ d->frameRate = qvariant_cast<qreal>(value);
+ } else if (qstrcmp(name, "pixelAspectRatio") == 0) {
+ if (qVariantCanConvert<QSize>(value))
+ d->pixelAspectRatio = qvariant_cast<QSize>(value);
+ } else if (qstrcmp(name, "sizeHint") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
+ if (qVariantCanConvert<YCbCrColorSpace>(value))
+ d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value);
+ } else {
+ int id = 0;
+ for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
+
+ if (id < d->propertyValues.count()) {
+ if (value.isNull()) {
+ d->propertyNames.removeAt(id);
+ d->propertyValues.removeAt(id);
+ } else {
+ d->propertyValues[id] = value;
+ }
+ } else if (!value.isNull()) {
+ d->propertyNames.append(QByteArray(name));
+ d->propertyValues.append(value);
+ }
+ }
+}
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QVideoSurfaceFormat &f)
+{
+ QString typeName;
+ switch (f.pixelFormat()) {
+ case QVideoFrame::Format_Invalid:
+ typeName = QLatin1String("Format_Invalid");
+ break;
+ case QVideoFrame::Format_ARGB32:
+ typeName = QLatin1String("Format_ARGB32");
+ break;
+ case QVideoFrame::Format_ARGB32_Premultiplied:
+ typeName = QLatin1String("Format_ARGB32_Premultiplied");
+ break;
+ case QVideoFrame::Format_RGB32:
+ typeName = QLatin1String("Format_RGB32");
+ break;
+ case QVideoFrame::Format_RGB24:
+ typeName = QLatin1String("Format_RGB24");
+ break;
+ case QVideoFrame::Format_RGB565:
+ typeName = QLatin1String("Format_RGB565");
+ break;
+ case QVideoFrame::Format_RGB555:
+ typeName = QLatin1String("Format_RGB555");
+ break;
+ case QVideoFrame::Format_ARGB8565_Premultiplied:
+ typeName = QLatin1String("Format_ARGB8565_Premultiplied");
+ break;
+ case QVideoFrame::Format_BGRA32:
+ typeName = QLatin1String("Format_BGRA32");
+ break;
+ case QVideoFrame::Format_BGRA32_Premultiplied:
+ typeName = QLatin1String("Format_BGRA32_Premultiplied");
+ break;
+ case QVideoFrame::Format_BGR32:
+ typeName = QLatin1String("Format_BGR32");
+ break;
+ case QVideoFrame::Format_BGR24:
+ typeName = QLatin1String("Format_BGR24");
+ break;
+ case QVideoFrame::Format_BGR565:
+ typeName = QLatin1String("Format_BGR565");
+ break;
+ case QVideoFrame::Format_BGR555:
+ typeName = QLatin1String("Format_BGR555");
+ break;
+ case QVideoFrame::Format_BGRA5658_Premultiplied:
+ typeName = QLatin1String("Format_BGRA5658_Premultiplied");
+ break;
+ case QVideoFrame::Format_AYUV444:
+ typeName = QLatin1String("Format_AYUV444");
+ break;
+ case QVideoFrame::Format_AYUV444_Premultiplied:
+ typeName = QLatin1String("Format_AYUV444_Premultiplied");
+ break;
+ case QVideoFrame::Format_YUV444:
+ typeName = QLatin1String("Format_YUV444");
+ break;
+ case QVideoFrame::Format_YUV420P:
+ typeName = QLatin1String("Format_YUV420P");
+ break;
+ case QVideoFrame::Format_YV12:
+ typeName = QLatin1String("Format_YV12");
+ break;
+ case QVideoFrame::Format_UYVY:
+ typeName = QLatin1String("Format_UYVY");
+ break;
+ case QVideoFrame::Format_YUYV:
+ typeName = QLatin1String("Format_YUYV");
+ break;
+ case QVideoFrame::Format_NV12:
+ typeName = QLatin1String("Format_NV12");
+ break;
+ case QVideoFrame::Format_NV21:
+ typeName = QLatin1String("Format_NV21");
+ break;
+ case QVideoFrame::Format_IMC1:
+ typeName = QLatin1String("Format_IMC1");
+ break;
+ case QVideoFrame::Format_IMC2:
+ typeName = QLatin1String("Format_IMC2");
+ break;
+ case QVideoFrame::Format_IMC3:
+ typeName = QLatin1String("Format_IMC3");
+ break;
+ case QVideoFrame::Format_IMC4:
+ typeName = QLatin1String("Format_IMC4");
+ break;
+ case QVideoFrame::Format_Y8:
+ typeName = QLatin1String("Format_Y8");
+ break;
+ case QVideoFrame::Format_Y16:
+ typeName = QLatin1String("Format_Y16");
+ default:
+ typeName = QString(QLatin1String("UserType(%1)" )).arg(int(f.pixelFormat()));
+ }
+
+ dbg.nospace() << "QVideoSurfaceFormat(" << typeName;
+ dbg.nospace() << ", " << f.frameSize();
+ dbg.nospace() << ", viewport=" << f.viewport();
+ dbg.nospace() << ", pixelAspectRatio=" << f.pixelAspectRatio();
+ dbg.nospace() << ")";
+
+ foreach(const QByteArray& propertyName, f.propertyNames())
+ dbg << "\n " << propertyName.data() << " = " << f.property(propertyName.data());
+
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE