diff options
Diffstat (limited to 'src/3rdparty/phonon/mmf/objectdump.cpp')
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump.cpp | 527 |
1 files changed, 527 insertions, 0 deletions
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 + + + |