diff options
author | Gareth Stockwell <gareth.stockwell@sosco.com> | 2009-09-07 10:26:02 (GMT) |
---|---|---|
committer | Gareth Stockwell <gareth.stockwell@sosco.com> | 2009-09-07 10:26:02 (GMT) |
commit | 386800053d03f3f42bc5d0e0809059b534bac5d4 (patch) | |
tree | 0b31c0d6d55d52892dce7861449f57d3ce32fe4a /src | |
parent | 65c8d29d8bad265a236431ab57b03f7b2614c53a (diff) | |
download | Qt-386800053d03f3f42bc5d0e0809059b534bac5d4.zip Qt-386800053d03f3f42bc5d0e0809059b534bac5d4.tar.gz Qt-386800053d03f3f42bc5d0e0809059b534bac5d4.tar.bz2 |
Added visitor-based object tree dumping framework, which dumps details of Symbian control / window associated with each widget
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/phonon/mmf/defs.h | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump.cpp | 527 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump.h | 164 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump_symbian.cpp | 129 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump_symbian.h | 56 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objecttree.cpp | 102 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objecttree.h | 115 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videooutput.cpp | 73 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videooutput.h | 8 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videoplayer.cpp | 24 | ||||
-rw-r--r-- | src/plugins/phonon/mmf/mmf.pro | 15 |
11 files changed, 1154 insertions, 61 deletions
diff --git a/src/3rdparty/phonon/mmf/defs.h b/src/3rdparty/phonon/mmf/defs.h index 674e767..60f363b 100644 --- a/src/3rdparty/phonon/mmf/defs.h +++ b/src/3rdparty/phonon/mmf/defs.h @@ -34,8 +34,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. // rect, i.e. QWidget::winId()->Rect() //#define PHONON_MMF_HARD_CODE_VIDEO_RECT -#define PHONON_MMF_DEBUG_VIDEO_OUTPUT - QT_BEGIN_NAMESPACE namespace Phonon diff --git a/src/3rdparty/phonon/mmf/objectdump.cpp b/src/3rdparty/phonon/mmf/objectdump.cpp new file mode 100644 index 0000000..50c6bf8 --- /dev/null +++ b/src/3rdparty/phonon/mmf/objectdump.cpp @@ -0,0 +1,527 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <QByteArray> +#include <QDebug> +#include <QHash> +#include <QTextStream> +#include <QWidget> + +#include "objectdump.h" +#include "objecttree.h" + +QT_BEGIN_NAMESPACE + +namespace ObjectDump +{ + +//----------------------------------------------------------------------------- +// QObjectAnnotator +//----------------------------------------------------------------------------- + +QAnnotator::~QAnnotator() +{ + +} + + +//----------------------------------------------------------------------------- +// Annotators +//----------------------------------------------------------------------------- + +QList<QByteArray> QAnnotatorBasic::annotation(const QObject& object) +{ + QList<QByteArray> result; + + QByteArray array; + QTextStream stream(&array); + + stream << '[' << &object << ']'; + stream << ' '; + stream << object.metaObject()->className(); + + if(object.objectName() != "") + stream << " \"" << object.objectName() << '"'; + + if(object.isWidgetType()) + stream << " isWidget"; + + stream.flush(); + result.append(array); + return result; +} + +QList<QByteArray> QAnnotatorWidget::annotation(const QObject& object) +{ + QList<QByteArray> result; + + const QWidget* widget = qobject_cast<const QWidget*>(&object); + if(widget) { + + QByteArray array; + QTextStream stream(&array); + + stream << "widget: "; + + if(widget->isVisible()) + stream << "visible "; + else + stream << "invisible "; + + stream << widget->x() << ',' << widget->y() << ' '; + stream << widget->size().width() << 'x'<< widget->size().height() << ' '; + + stream << "hint " << widget->sizeHint().width() << 'x' << widget->sizeHint().height(); + + stream.flush(); + result.append(array); + } + + return result; +} + + +//----------------------------------------------------------------------------- +// Base class for QDumperPrivate, QVisitorPrivate +//----------------------------------------------------------------------------- + +class QDumperBase +{ +public: + QDumperBase(); + ~QDumperBase(); + + void setPrefix(const QString& prefix); + void addAnnotator(QAnnotator* annotator); + +protected: + QByteArray m_prefix; + QList<QAnnotator*> m_annotators; + +}; + +QDumperBase::QDumperBase() +{ + +} + +QDumperBase::~QDumperBase() +{ + QAnnotator* annotator; + foreach(annotator, m_annotators) + delete annotator; +} + +void QDumperBase::setPrefix(const QString& prefix) +{ + m_prefix = prefix.count() + ? (prefix + " ").toAscii() + : prefix.toAscii(); +} + +void QDumperBase::addAnnotator(QAnnotator* annotator) +{ + // Protect against an exception occurring during QList::append + QScopedPointer<QAnnotator> holder(annotator); + m_annotators.append(annotator); + holder.take(); +} + + +//----------------------------------------------------------------------------- +// QDumper +//----------------------------------------------------------------------------- + +class QDumperPrivate : public QDumperBase +{ +public: + QDumperPrivate(); + ~QDumperPrivate(); + + void dumpObject(const QObject& object); + +}; + + +QDumperPrivate::QDumperPrivate() +{ + +} + +QDumperPrivate::~QDumperPrivate() +{ + +} + +void QDumperPrivate::dumpObject(const QObject& object) +{ + QAnnotator* annotator; + foreach(annotator, m_annotators) { + + const QList<QByteArray> annotations = annotator->annotation(object); + QByteArray annotation; + foreach(annotation, annotations) { + QByteArray buffer(m_prefix); + buffer.append(annotation); + qDebug() << buffer.constData(); + } + } +} + + +QDumper::QDumper() + : d_ptr(new QDumperPrivate) +{ + +} + +QDumper::~QDumper() +{ + +} + +void QDumper::setPrefix(const QString& prefix) +{ + d_func()->setPrefix(prefix); +} + +void QDumper::addAnnotator(QAnnotator* annotator) +{ + d_func()->addAnnotator(annotator); +} + +void QDumper::dumpObject(const QObject& object) +{ + d_func()->dumpObject(object); +} + + +//----------------------------------------------------------------------------- +// QVisitor +//----------------------------------------------------------------------------- + +class QVisitorPrivate : public QDumperBase +{ +public: + QVisitorPrivate(); + ~QVisitorPrivate(); + + void setIndent(unsigned indent); + + void visitNode(const QObject& object); + void visitComplete(); + +private: + class Node + { + public: + Node(); + ~Node(); + + QList<QByteArray> m_annotation; + QList<Node*> m_children; + + typedef QList<Node*>::const_iterator child_iterator; + }; + +private: + Node* findNode(const QObject* object) const; + QByteArray branchBuffer(const QList<bool>& branches, bool isNodeLine, bool isLastChild) const; + void dumpRecursive(const Node& node, QList<bool> branches, bool isLastChild); + void dumpNode(const Node& node, const QList<bool>& branches, bool isLastChild); + +private: + unsigned m_indent; + + QScopedPointer<Node> m_root; + + // Hash table used to associate internal nodes with QObjects + typedef QHash<const QObject*, Node*> Hash; + Hash m_hash; +}; + +static const unsigned DefaultIndent = 2; + +QVisitorPrivate::QVisitorPrivate() + : m_indent(DefaultIndent) +{ + +} + +QVisitorPrivate::~QVisitorPrivate() +{ + +} + +void QVisitorPrivate::setIndent(unsigned indent) +{ + m_indent = indent; +} + +// Builds up a mirror of the object tree, rooted in m_root, with each node +// storing annotations generated by +void QVisitorPrivate::visitNode(const QObject& object) +{ + QObject* const objectParent = object.parent(); + Node* const nodeParent = objectParent ? findNode(objectParent) : NULL; + + // Create a new node and store in scoped pointer for exception safety + Node* node = new Node; + QScopedPointer<Node> nodePtr(node); + + // Associate node with QObject + m_hash.insert(&object, node); + + // Insert node into internal tree + if(nodeParent) + { + nodeParent->m_children.append(nodePtr.take()); + } + else + { + Q_ASSERT(m_root.isNull()); + m_root.reset(nodePtr.take()); + } + + // Generate and store annotations + QAnnotator* annotator; + foreach(annotator, m_annotators) + node->m_annotation.append( annotator->annotation(object) ); +} + +void QVisitorPrivate::visitComplete() +{ + QList<bool> branches; + static const bool isLastChild = true; + dumpRecursive(*m_root, branches, isLastChild); + m_root.reset(NULL); +} + +QVisitorPrivate::Node* QVisitorPrivate::findNode(const QObject* object) const +{ + Hash::const_iterator i = m_hash.find(object); + return (m_hash.end() == i) ? NULL : *i; +} + +QByteArray QVisitorPrivate::branchBuffer + (const QList<bool>& branches, bool isNodeLine, bool isLastChild) const +{ + const int depth = branches.count(); + + const QByteArray indent(m_indent, ' '); + const QByteArray horiz(m_indent, '-'); + + QByteArray buffer; + QTextStream stream(&buffer); + + for (int i=0; i<depth-1; ++i) { + if(branches[i]) + stream << '|'; + else + stream << ' '; + stream << indent; + } + + if(depth) { + if(isNodeLine) + stream << '+' << horiz; + else { + if(!isLastChild) + stream << '|'; + else + stream << ' '; + stream << indent; + } + } + + stream.flush(); + buffer.push_front(m_prefix); + + return buffer; +} + +void QVisitorPrivate::dumpRecursive + (const Node& node, QList<bool> branches, bool isLastChild) +{ + dumpNode(node, branches, isLastChild); + + // Recurse down tree + const Node::child_iterator begin = node.m_children.begin(); + const Node::child_iterator end = node.m_children.end(); + for(Node::child_iterator i = begin; end != i; ++i) { + + isLastChild = (end == i + 1); + + if(begin == i) + branches.push_back(!isLastChild); + else + branches.back() = !isLastChild; + + static const bool isNodeLine = false; + const QByteArray buffer = branchBuffer(branches, isNodeLine, false); + qDebug() << buffer.constData(); + + dumpRecursive(**i, branches, isLastChild); + } +} + +void QVisitorPrivate::dumpNode + (const Node& node, const QList<bool>& branches, bool isLastChild) +{ + const QList<QByteArray>::const_iterator + begin = node.m_annotation.begin(), end = node.m_annotation.end(); + + if(begin == end) { + // No annotations - just dump the object pointer + const bool isNodeLine = true; + QByteArray buffer = branchBuffer(branches, isNodeLine, isLastChild); + qDebug() << NULL; // TODO + } + else { + // Dump annotations + for(QList<QByteArray>::const_iterator i = begin; end != i; ++i) { + const bool isNodeLine = (begin == i); + QByteArray buffer = branchBuffer(branches, isNodeLine, isLastChild); + buffer.append(*i); + qDebug() << buffer.constData(); + } + } +} + + +// QVisitorPrivate::Node + +QVisitorPrivate::Node::Node() +{ + +} + +QVisitorPrivate::Node::~Node() +{ + Node* child; + foreach(child, m_children) + delete child; +} + + +// QVisitor + +QVisitor::QVisitor() + : d_ptr(new QVisitorPrivate) +{ + +} + +QVisitor::~QVisitor() +{ + +} + +void QVisitor::setPrefix(const QString& prefix) +{ + d_func()->setPrefix(prefix); +} + +void QVisitor::setIndent(unsigned indent) +{ + d_func()->setIndent(indent); +} + +void QVisitor::addAnnotator(QAnnotator* annotator) +{ + d_func()->addAnnotator(annotator); +} + +void QVisitor::visitPrepare() +{ + // Do nothing +} + +void QVisitor::visitNode(const QObject& object) +{ + d_func()->visitNode(object); +} + +void QVisitor::visitComplete() +{ + d_func()->visitComplete(); +} + + +//----------------------------------------------------------------------------- +// Utility functions +//----------------------------------------------------------------------------- + +void addDefaultAnnotators_sys(QDumper& visitor); +void addDefaultAnnotators_sys(QVisitor& visitor); + +void addDefaultAnnotators(QDumper& dumper) +{ + dumper.addAnnotator(new QAnnotatorBasic); + dumper.addAnnotator(new QAnnotatorWidget); + + // Add platform-specific annotators + addDefaultAnnotators_sys(dumper); +} + +void addDefaultAnnotators(QVisitor& visitor) +{ + visitor.addAnnotator(new QAnnotatorBasic); + visitor.addAnnotator(new QAnnotatorWidget); + + // Add platform-specific annotators + addDefaultAnnotators_sys(visitor); +} + +void dumpTreeFromRoot(const QObject& root, QVisitor& visitor) +{ + // Set up iteration range + ObjectTree::DepthFirstConstIterator begin(root), end; + + // Invoke generic visitor algorithm + ObjectTree::visit(begin, end, visitor); +} + +void dumpTreeFromLeaf(const QObject& leaf, QVisitor& visitor) +{ + // Walk up to root + const QObject* root = &leaf; + while(root->parent()) + { + root = root->parent(); + } + + dumpTreeFromRoot(*root, visitor); +} + +void dumpAncestors(const QObject& leaf, QVisitor& visitor) +{ + // Set up iteration range + ObjectTree::AncestorConstIterator begin(leaf), end; + + // Invoke generic visitor algorithm + ObjectTree::visit(begin, end, visitor); +} + + +} // namespace ObjectDump + +QT_END_NAMESPACE + + + diff --git a/src/3rdparty/phonon/mmf/objectdump.h b/src/3rdparty/phonon/mmf/objectdump.h new file mode 100644 index 0000000..4efc015 --- /dev/null +++ b/src/3rdparty/phonon/mmf/objectdump.h @@ -0,0 +1,164 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef OBJECTDUMP_H +#define OBJECTDUMP_H + +#include <QObject> +#include <QList> +#include <QByteArray> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +namespace ObjectDump +{ + +/** + * Abstract base for annotator classes invoked by QVisitor. + */ +class QAnnotator : public QObject +{ + Q_OBJECT +public: + virtual ~QAnnotator(); + virtual QList<QByteArray> annotation(const QObject& object) = 0; +}; + +/** + * Annotator which replicates QObject::dumpObjectTree functionality. + */ +class QAnnotatorBasic : public QAnnotator +{ + Q_OBJECT +public: + QList<QByteArray> annotation(const QObject& object); +}; + +/** + * Annotator which returns widget information. + */ +class QAnnotatorWidget : public QAnnotator +{ + Q_OBJECT +public: + QList<QByteArray> annotation(const QObject& object); +}; + + +class QDumperPrivate; + +/** + * Class used to dump information about individual QObjects. + */ +class QDumper : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDumper) + +public: + QDumper(); + ~QDumper(); + + /** + * Specify a prefix, to be printed on each line of output. + */ + void setPrefix(const QString& prefix); + + /** + * Takes ownership of annotator. + */ + void addAnnotator(QAnnotator* annotator); + + /** + * Invoke each annotator on the object and write to debug output. + */ + void dumpObject(const QObject& object); + +private: + QScopedPointer<QDumperPrivate> d_ptr; + +}; + + +class QVisitorPrivate; + +/** + * Visitor class which dumps information about nodes in the object tree. + */ +class QVisitor : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QVisitor) + +public: + QVisitor(); + ~QVisitor(); + + /** + * Specify a prefix, to be printed on each line of output. + */ + void setPrefix(const QString& prefix); + + /** + * Set number of spaces by which each level of the tree is indented. + */ + void setIndent(unsigned indent); + + /** + * Called by the visitor algorithm before starting the visit. + */ + void visitPrepare(); + + /** + * Called by the visitor algorithm as each node is visited. + */ + void visitNode(const QObject& object); + + /** + * Called by the visitor algorithm when the visit is complete. + */ + void visitComplete(); + + /** + * Takes ownership of annotator. + */ + void addAnnotator(QAnnotator* annotator); + +private: + QScopedPointer<QVisitorPrivate> d_ptr; + +}; + + +//----------------------------------------------------------------------------- +// Utility functions +//----------------------------------------------------------------------------- + +void addDefaultAnnotators(QDumper& dumper); +void addDefaultAnnotators(QVisitor& visitor); + +void dumpTreeFromRoot(const QObject& root, QVisitor& visitor); +void dumpTreeFromLeaf(const QObject& leaf, QVisitor& visitor); +void dumpAncestors(const QObject& leaf, QVisitor& visitor); + +} // namespace ObjectDump + +QT_END_NAMESPACE + +#endif diff --git a/src/3rdparty/phonon/mmf/objectdump_symbian.cpp b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp new file mode 100644 index 0000000..54ebc55 --- /dev/null +++ b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp @@ -0,0 +1,129 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <QTextStream> +#include <QWidget> +#include <coecntrl.h> +#include "objectdump_symbian.h" + +QT_BEGIN_NAMESPACE + +namespace ObjectDump +{ +namespace Symbian +{ + +QList<QByteArray> QAnnotatorControl::annotation(const QObject& object) +{ + QList<QByteArray> result; + + const QWidget* widget = qobject_cast<const QWidget*>(&object); + if(widget) { + + const CCoeControl* control = widget->effectiveWinId(); + if(control) { + + QByteArray array; + QTextStream stream(&array); + + stream << "control: " << control << ' '; + stream << "parent " << control->Parent() << ' '; + + if(control->IsVisible()) + stream << "visible "; + else + stream << "invisible "; + + stream << control->Position().iX << ',' << control->Position().iY << ' '; + stream << control->Size().iWidth << 'x' << control->Size().iHeight; + + if(control->OwnsWindow()) + stream << " ownsWindow "; + + stream.flush(); + result.append(array); + } + } + + return result; +} + +QList<QByteArray> QAnnotatorWindow::annotation(const QObject& object) +{ + QList<QByteArray> result; + + const QWidget* widget = qobject_cast<const QWidget*>(&object); + if(widget) { + + const CCoeControl* control = widget->effectiveWinId(); + if(control) { + + RDrawableWindow& window = *(control->DrawableWindow()); + + QByteArray array; + QTextStream stream(&array); + + stream << "window: "; + + // Client-side window handle + // Cast to a void pointer so that log output is in hexadecimal format. + stream << "cli " << reinterpret_cast<const void*>(window.ClientHandle()) << ' '; + + // Server-side address of CWsWindow object + // This is useful for correlation with the window tree dumped by the window + // server (see RWsSession::LogCommand). + // Cast to a void pointer so that log output is in hexadecimal format. + stream << "srv " << reinterpret_cast<const void*>(window.WsHandle()) << ' '; + + stream << "group " << window.WindowGroupId() << ' '; + + // Client-side handle to the parent window. + // Cast to a void pointer so that log output is in hexadecimal format. + stream << "parent " << reinterpret_cast<const void*>(window.Parent()) << ' '; + + stream << window.Position().iX << ',' << window.Position().iY << ' '; + stream << '(' << window.AbsPosition().iX << ',' << window.AbsPosition().iY << ") "; + stream << window.Size().iWidth << 'x' << window.Size().iHeight; + + stream.flush(); + result.append(array); + } + } + + return result; +} + +} // namespace Symbian + +void addDefaultAnnotators_sys(QDumper& dumper) +{ + dumper.addAnnotator(new Symbian::QAnnotatorControl); + dumper.addAnnotator(new Symbian::QAnnotatorWindow); +} + +void addDefaultAnnotators_sys(QVisitor& visitor) +{ + visitor.addAnnotator(new Symbian::QAnnotatorControl); + visitor.addAnnotator(new Symbian::QAnnotatorWindow); +} + +} // namespace ObjectDump + +QT_END_NAMESPACE + + diff --git a/src/3rdparty/phonon/mmf/objectdump_symbian.h b/src/3rdparty/phonon/mmf/objectdump_symbian.h new file mode 100644 index 0000000..26ab308 --- /dev/null +++ b/src/3rdparty/phonon/mmf/objectdump_symbian.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef OBJECTDUMP_SYMBIAN_H +#define OBJECTDUMP_SYMBIAN_H + +#include "objectdump.h" + +QT_BEGIN_NAMESPACE + +namespace ObjectDump +{ +namespace Symbian +{ + +/** + * Annotator which returns control information + */ +class QAnnotatorControl : public QAnnotator +{ + Q_OBJECT +public: + QList<QByteArray> annotation(const QObject& object); +}; + +/** + * Annotator which returns window information + */ +class QAnnotatorWindow : public QAnnotator +{ + Q_OBJECT +public: + QList<QByteArray> annotation(const QObject& object); +}; + +} // namespace Symbian +} // namespace ObjectDump + +QT_END_NAMESPACE + +#endif diff --git a/src/3rdparty/phonon/mmf/objecttree.cpp b/src/3rdparty/phonon/mmf/objecttree.cpp new file mode 100644 index 0000000..f9d1c93 --- /dev/null +++ b/src/3rdparty/phonon/mmf/objecttree.cpp @@ -0,0 +1,102 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <QTextStream> +#include <QWidget> +#include "objecttree.h" + +QT_BEGIN_NAMESPACE + +namespace ObjectTree +{ + +DepthFirstConstIterator::DepthFirstConstIterator() + : m_pointee(NULL) +{ + +} + +DepthFirstConstIterator::DepthFirstConstIterator + (const QObject& root) + : m_pointee(&root) +{ + +} + +DepthFirstConstIterator& + DepthFirstConstIterator::operator++() +{ + const QObjectList& children = m_pointee->children(); + + if (children.count() == 0) { + backtrack(); + } + else { + m_history.push(0); + m_pointee = children.first(); + } + + return *this; +} + +void DepthFirstConstIterator::backtrack() +{ + if (m_history.count()) { + const int index = m_history.top(); + m_history.pop(); + + const QObjectList& siblings = m_pointee->parent()->children(); + if (siblings.count() > index + 1) { + m_history.push(index + 1); + m_pointee = siblings[index + 1]; + } + else { + m_pointee = m_pointee->parent(); + backtrack(); + } + } + else { + // Reached end of search + m_pointee = NULL; + } +} + + + +AncestorConstIterator::AncestorConstIterator() +{ + +} + +AncestorConstIterator::AncestorConstIterator(const QObject& leaf) +{ + m_ancestors.push(&leaf); + QObject* ancestor = leaf.parent(); + while(ancestor) + { + m_ancestors.push(ancestor); + ancestor = ancestor->parent(); + } +} + +} // namespace ObjectTree + +QT_END_NAMESPACE + + + diff --git a/src/3rdparty/phonon/mmf/objecttree.h b/src/3rdparty/phonon/mmf/objecttree.h new file mode 100644 index 0000000..0c2031d --- /dev/null +++ b/src/3rdparty/phonon/mmf/objecttree.h @@ -0,0 +1,115 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef OBJECTTREE_H +#define OBJECTTREE_H + +#include <QObject> +#include <QStack> + +QT_BEGIN_NAMESPACE + +namespace ObjectTree +{ + +/** + * Depth-first iterator for QObject tree + */ +class DepthFirstConstIterator +{ +public: + DepthFirstConstIterator(); + DepthFirstConstIterator(const QObject& root); + + DepthFirstConstIterator& operator++(); + + inline bool operator==(const DepthFirstConstIterator& other) const + { return other.m_pointee == m_pointee; } + + inline bool operator!=(const DepthFirstConstIterator& other) const + { return other.m_pointee != m_pointee; } + + inline const QObject* operator->() const { return m_pointee; } + inline const QObject& operator*() const { return *m_pointee; } + +private: + void backtrack(); + +private: + const QObject* m_pointee; + QStack<int> m_history; +}; + +/** + * Ancestor iterator for QObject tree + */ +class AncestorConstIterator +{ +public: + AncestorConstIterator(); + AncestorConstIterator(const QObject& root); + + inline AncestorConstIterator& operator++() + { m_ancestors.pop(); return *this; } + + inline bool operator==(const AncestorConstIterator& other) const + { return other.m_ancestors == m_ancestors; } + + inline bool operator!=(const AncestorConstIterator& other) const + { return other.m_ancestors != m_ancestors; } + + inline const QObject* operator->() const { return m_ancestors.top(); } + inline const QObject& operator*() const { return *m_ancestors.top(); } + +private: + QStack<const QObject*> m_ancestors; + +}; + +/** + * Generic algorithm for visiting nodes in an object tree. Nodes in the + * tree are visited in a const context, therefore they are not modified + * by this algorithm. + * + * Visitor must provide functions with the following signatures: + * + * Called before visit begins + * void visitPrepare() + * + * Called on each node visited + * void visitNode(const QObject& object) + * + * Called when visit is complete + * void visitComplete() + */ +template <class Iterator, class Visitor> +void visit(Iterator begin, Iterator end, Visitor& visitor) +{ + visitor.visitPrepare(); + + for( ; begin != end; ++begin) + visitor.visitNode(*begin); + + visitor.visitComplete(); +} + +} // namespace ObjectTree + +QT_END_NAMESPACE + +#endif // OBJECTTREE_H diff --git a/src/3rdparty/phonon/mmf/videooutput.cpp b/src/3rdparty/phonon/mmf/videooutput.cpp index c517c22..2544a97 100644 --- a/src/3rdparty/phonon/mmf/videooutput.cpp +++ b/src/3rdparty/phonon/mmf/videooutput.cpp @@ -20,6 +20,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "videooutput.h" #include "videooutputobserver.h" +#ifdef _DEBUG +#include "objectdump.h" +#endif + #include <QPaintEvent> #include <QPainter> #include <QMoveEvent> @@ -48,59 +52,10 @@ MMF::VideoOutput::VideoOutput(QWidget* parent) setAutoFillBackground(false); #endif // PHONON_MMF_VIDEOOUTPUT_IS_QWIDGET -#ifdef PHONON_MMF_DEBUG_VIDEO_OUTPUT dump(); -#endif - - TRACE_EXIT_0(); -} - -#ifdef PHONON_MMF_DEBUG_VIDEO_OUTPUT -void VideoOutput::dump() -{ - TRACE_CONTEXT(VideoOutput::dump, EVideoInternal); - TRACE_ENTRY_0(); - - TRACE("dumpObjectInfo this 0x%08x", this); - this->dumpObjectInfo(); - - TRACE_0("Traversing up object tree ..."); - QObject* node = this; - QObject* root = this; - while (node) { - QWidget* widget = qobject_cast<QWidget*>(node); - const bool visible = widget ? widget->isVisible() : false; - const QHBufC name(node->objectName()); - TRACE("node 0x%08x name %S widget 0x%08x visible %d", node, name.data(), widget, visible); - - root = node; - node = node->parent(); - } - - TRACE("dumpObjectInfo root 0x%08x", root); - root->dumpObjectInfo(); - TRACE_0("+ dumpObjectTree"); - root->dumpObjectTree(); - TRACE_0("- dumpObjectTree"); - - TRACE("isVisible %d", isVisible()); - TRACE("pos %d %d", x(), y()); - TRACE("size %d %d", size().width(), size().height()); - TRACE("maxSize %d %d", maximumWidth(), maximumHeight()); - TRACE("sizeHint %d %d", sizeHint().width(), sizeHint().height()); - - QWidget* parentWidget = qobject_cast<QWidget*>(parent()); - if (parentWidget) { - TRACE("parent.isVisible %d", parentWidget->isVisible()); - TRACE("parent.pos %d %d", parentWidget->x(), parentWidget->y()); - TRACE("parent.size %d %d", parentWidget->size().width(), parentWidget->size().height()); - TRACE("parent.maxSize %d %d", parentWidget->maximumWidth(), parentWidget->maximumHeight()); - TRACE("parent.sizeHint %d %d", parentWidget->sizeHint().width(), parentWidget->sizeHint().height()); - } - + TRACE_EXIT_0(); } -#endif // PHONON_MMF_DEBUG_VIDEO_OUTPUT MMF::VideoOutput::~VideoOutput() { @@ -144,8 +99,6 @@ void MMF::VideoOutput::setObserver(VideoOutputObserver* observer) QSize MMF::VideoOutput::sizeHint() const { - TRACE_CONTEXT(VideoOutput::sizeHint, EVideoApi); - // TODO: replace this with a more sensible default QSize result(320, 240); @@ -153,7 +106,6 @@ QSize MMF::VideoOutput::sizeHint() const result = m_frameSize; } - TRACE(" result %d %d", result.width(), result.height()); return result; } @@ -166,6 +118,8 @@ void MMF::VideoOutput::paintEvent(QPaintEvent* event) TRACE("regions %d", event->region().numRects()); TRACE("type %d", event->type()); + dump(); + /* QPainter painter; painter.begin(this); @@ -208,6 +162,19 @@ void MMF::VideoOutput::moveEvent(QMoveEvent* event) // Private functions //----------------------------------------------------------------------------- +void VideoOutput::dump() const +{ +#ifdef _DEBUG + TRACE_CONTEXT(VideoOutput::dump, EVideoInternal); + QScopedPointer<ObjectDump::QVisitor> visitor(new ObjectDump::QVisitor); + visitor->setPrefix("Phonon::MMF"); // to aid searchability of logs + ObjectDump::addDefaultAnnotators(*visitor); + TRACE("Dumping tree from leaf 0x%08x:", this); + //ObjectDump::dumpAncestors(*this, *visitor); + ObjectDump::dumpTreeFromLeaf(*this, *visitor); +#endif +} + QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h index bcd9cb4..566d065 100644 --- a/src/3rdparty/phonon/mmf/videooutput.h +++ b/src/3rdparty/phonon/mmf/videooutput.h @@ -50,11 +50,9 @@ protected: void moveEvent(QMoveEvent* event); #endif // PHONON_MMF_VIDEOOUTPUT_IS_QWIDGET -#ifdef PHONON_MMF_DEBUG_VIDEO_OUTPUT -public: - void dump(); -#endif - +private: + void dump() const; + private: QSize m_frameSize; diff --git a/src/3rdparty/phonon/mmf/videoplayer.cpp b/src/3rdparty/phonon/mmf/videoplayer.cpp index 736d74f..a73c6ec 100644 --- a/src/3rdparty/phonon/mmf/videoplayer.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer.cpp @@ -26,6 +26,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "videoplayer.h" #include "utils.h" +#ifdef _DEBUG +#include "objectdump.h" +#endif + QT_BEGIN_NAMESPACE using namespace Phonon; @@ -398,10 +402,17 @@ void MMF::VideoPlayer::videoOutputChanged() void MMF::VideoPlayer::getNativeWindowSystemHandles() { TRACE_CONTEXT(VideoPlayer::getNativeWindowSystemHandles, EVideoInternal); + TRACE_ENTRY_0(); VideoOutput& output = videoOutput(); CCoeControl* const control = output.winId(); - + + CCoeEnv* const coeEnv = control->ControlEnv(); + m_wsSession = &(coeEnv->WsSession()); + m_screenDevice = coeEnv->ScreenDevice(); + m_window = control->DrawableWindow(); + +/* TRACE("control 0x%08x", control); TRACE("control IsVisible %d", control->IsVisible()); TRACE("control IsDimmed %d", control->IsDimmed()); @@ -434,6 +445,15 @@ void MMF::VideoPlayer::getNativeWindowSystemHandles() m_window->AbsPosition().iX, m_window->AbsPosition().iY); TRACE("window Size %d %d", m_window->Size().iWidth, m_window->Size().iHeight); +*/ + +#ifdef _DEBUG + QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper); + dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs + ObjectDump::addDefaultAnnotators(*dumper); + TRACE_0("Dumping VideoOutput:"); + dumper->dumpObject(output); +#endif #ifdef PHONON_MMF_HARD_CODE_VIDEO_RECT // HACK: why isn't control->Rect updated following a call to @@ -455,6 +475,8 @@ void MMF::VideoPlayer::getNativeWindowSystemHandles() TRACE("clipRect %d %d - %d %d", m_clipRect.iTl.iX, m_clipRect.iTl.iY, m_clipRect.iBr.iX, m_clipRect.iBr.iY); + + TRACE_EXIT_0(); } diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 1d9910b..56cc37a 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -49,6 +49,21 @@ SOURCES += \ $$PHONON_MMF_DIR/videooutput.cpp \ $$PHONON_MMF_DIR/videoplayer.cpp \ $$PHONON_MMF_DIR/videowidget.cpp + +# This is not mmfphonon-specific, and should be factored out into a separate +# library (QtCore?) at a later date +debug { +HEADERS += \ + $$PHONON_MMF_DIR/objectdump.h \ + $$PHONON_MMF_DIR/objectdump_symbian.h \ + $$PHONON_MMF_DIR/objecttree.h + +SOURCES += \ + $$PHONON_MMF_DIR/objectdump.cpp \ + $$PHONON_MMF_DIR/objectdump_symbian.cpp \ + $$PHONON_MMF_DIR/objecttree.cpp + +} LIBS += -lmediaclientvideo.lib # For CVideoPlayerUtility LIBS += -lcone.lib # For CCoeEnv |