summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/mmf/objectdump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/phonon/mmf/objectdump.cpp')
-rw-r--r--src/3rdparty/phonon/mmf/objectdump.cpp527
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
+
+
+