diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-10-22 01:59:33 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-10-22 01:59:33 (GMT) |
commit | 6c9ac788a60fcd2f946787a5297d7c2f71ad1968 (patch) | |
tree | af53424d7d2adfcbb324624ab93d31845d3db80d /tools | |
parent | 2391cf5d127882ce8811e058115d5c2605328079 (diff) | |
parent | fa85d539decf7bdcb16fa8f52858b13479cea659 (diff) | |
download | Qt-6c9ac788a60fcd2f946787a5297d7c2f71ad1968.zip Qt-6c9ac788a60fcd2f946787a5297d7c2f71ad1968.tar.gz Qt-6c9ac788a60fcd2f946787a5297d7c2f71ad1968.tar.bz2 |
Merge branch 'kinetic-declarativeui' of scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qdoc3/cppcodemarker.cpp | 4 | ||||
-rw-r--r-- | tools/qdoc3/node.h | 4 | ||||
-rw-r--r-- | tools/qdoc3/qmlcodemarker.cpp | 1175 | ||||
-rw-r--r-- | tools/qdoc3/qmlcodemarker.h | 96 | ||||
-rw-r--r-- | tools/qmldebugger/expressionquerywidget.cpp | 216 | ||||
-rw-r--r-- | tools/qmldebugger/expressionquerywidget.h | 62 | ||||
-rw-r--r-- | tools/qmldebugger/objectpropertiesview.cpp | 23 | ||||
-rw-r--r-- | tools/qmldebugger/objecttree.cpp | 10 | ||||
-rw-r--r-- | tools/qmldebugger/objecttree.h | 6 | ||||
-rw-r--r-- | tools/qmldebugger/qmldebugger.cpp | 4 | ||||
-rw-r--r-- | tools/qmldebugger/qmldebugger.pri | 6 | ||||
-rw-r--r-- | tools/qmldebugger/watchtable.cpp | 3 | ||||
-rw-r--r-- | tools/qmlviewer/qmlviewer.cpp | 8 |
13 files changed, 1598 insertions, 19 deletions
diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 3bee3d9..30ea251 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -353,6 +353,10 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) QString name = taggedQmlNode(node); if (summary) { name = linkTag(node,name); + } else if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node); + if (pn->isAttached()) + name.prepend(pn->element() + QLatin1Char('.')); } name = "<@name>" + name + "</@name>"; QString synopsis = name; diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index c6f860f..6b19f60 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -376,7 +376,7 @@ class QmlPropGroupNode : public FakeNode bool attached); virtual ~QmlPropGroupNode() { } - const QString& element() const { return name(); } + const QString& element() const { return parent()->name(); } void setDefault() { isdefault = true; } bool isDefault() const { return isdefault; } bool isAttached() const { return att; } @@ -405,7 +405,7 @@ class QmlPropertyNode : public LeafNode bool isDesignable() const { return fromTrool(des,false); } bool isAttached() const { return att; } - const QString& element() const { return parent()->name(); } + const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); } private: enum Trool { Trool_True, Trool_False, Trool_Default }; diff --git a/tools/qdoc3/qmlcodemarker.cpp b/tools/qdoc3/qmlcodemarker.cpp new file mode 100644 index 0000000..1062f9c --- /dev/null +++ b/tools/qdoc3/qmlcodemarker.cpp @@ -0,0 +1,1175 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications 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$ +** +****************************************************************************/ + +/* + cppcodemarker.cpp +*/ + +#include <qdebug.h> +#include "atom.h" +#include "cppcodemarker.h" +#include "node.h" +#include "text.h" +#include "tree.h" + +QT_BEGIN_NAMESPACE + +static int insertTagAround(QString &result, int pos, int len, const QString &tagName, + const QString &attributes = QString()) +{ + QString s; + //s.reserve(result.size() + tagName.size() * 2 + attributes.size() + 20); + s += result.midRef(0, pos); + s += QLatin1Char('<'); + s += tagName; + if (!attributes.isEmpty()) { + s += QLatin1Char(' '); + s += attributes; + } + s += QLatin1Char('>'); + s += result.midRef(pos, len); + s += QLatin1String("</"); + s += tagName; + s += QLatin1Char('>'); + s += result.midRef(pos + len); + int diff = s.length() - result.length(); + result = s; + return diff; +} + +/*! + The constructor does nothing. + */ +CppCodeMarker::CppCodeMarker() +{ + // nothing. +} + +/*! + The destructor does nothing. + */ +CppCodeMarker::~CppCodeMarker() +{ + // nothing. +} + +/*! + Returns true. + */ +bool CppCodeMarker::recognizeCode(const QString & /* code */) +{ + return true; +} + +/*! + Returns true if \a ext is any of a list of file extensions + for the C++ language. + */ +bool CppCodeMarker::recognizeExtension(const QString& ext) +{ + return ext == "c" || + ext == "c++" || + ext == "cc" || + ext == "cpp" || + ext == "cxx" || + ext == "ch" || + ext == "h" || + ext == "h++" || + ext == "hh" || + ext == "hpp" || + ext == "hxx"; +} + +/*! + Returns true if \a lang is either "C" or "Cpp". + */ +bool CppCodeMarker::recognizeLanguage(const QString &lang) +{ + return lang == "C" || lang == "Cpp"; +} + +/*! + Returns the \a node name, or "()" if \a node is a + Node::Function node. + */ +QString CppCodeMarker::plainName(const Node *node) +{ + QString name = node->name(); + if (node->type() == Node::Function) + name += "()"; + return name; +} + +QString CppCodeMarker::plainFullName(const Node *node, const Node *relative) +{ + if (node->name().isEmpty()) { + return "global"; + } + else { + QString fullName; + for (;;) { + fullName.prepend(plainName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("::"); + node = node->parent(); + } + return fullName; + } +} + +QString CppCodeMarker::markedUpCode(const QString &code, + const Node *relative, + const QString &dirPath) +{ + return addMarkUp(protect(code), relative, dirPath); +} + +QString CppCodeMarker::markedUpSynopsis(const Node *node, + const Node * /* relative */, + SynopsisStyle style) +{ + const int MaxEnumValues = 6; + const FunctionNode *func; + const PropertyNode *property; + const VariableNode *variable; + const EnumNode *enume; + const TypedefNode *typedeff; + QString synopsis; + QString extra; + QString name; + + name = taggedNode(node); + if (style != Detailed) + name = linkTag(node, name); + name = "<@name>" + name + "</@name>"; + + if (style == Detailed && !node->parent()->name().isEmpty() && + node->type() != Node::Property) + name.prepend(taggedNode(node->parent()) + "::"); + + switch (node->type()) { + case Node::Namespace: + synopsis = "namespace " + name; + break; + case Node::Class: + synopsis = "class " + name; + break; + case Node::Function: + func = (const FunctionNode *) node; + if (style != SeparateList && !func->returnType().isEmpty()) + synopsis = typified(func->returnType()) + " "; + synopsis += name; + if (func->metaness() != FunctionNode::MacroWithoutParams) { + synopsis += " ("; + if (!func->parameters().isEmpty()) { + synopsis += " "; + QList<Parameter>::ConstIterator p = func->parameters().begin(); + while (p != func->parameters().end()) { + if (p != func->parameters().begin()) + synopsis += ", "; + synopsis += typified((*p).leftType()); + if (style != SeparateList && !(*p).name().isEmpty()) + synopsis += + " <@param>" + protect((*p).name()) + "</@param>"; + synopsis += protect((*p).rightType()); + if (style != SeparateList && !(*p).defaultValue().isEmpty()) + synopsis += " = " + protect((*p).defaultValue()); + ++p; + } + synopsis += " "; + } + synopsis += ")"; + } + if (func->isConst()) + synopsis += " const"; + + if (style == Summary || style == Accessors) { + if (func->virtualness() != FunctionNode::NonVirtual) + synopsis.prepend("virtual "); + if (func->virtualness() == FunctionNode::PureVirtual) + synopsis.append(" = 0"); + } + else if (style == SeparateList) { + if (!func->returnType().isEmpty() && func->returnType() != "void") + synopsis += " : " + typified(func->returnType()); + } + else { + QStringList bracketed; + if (func->isStatic()) { + bracketed += "static"; + } + else if (func->virtualness() != FunctionNode::NonVirtual) { + if (func->virtualness() == FunctionNode::PureVirtual) + bracketed += "pure"; + bracketed += "virtual"; + } + + if (func->access() == Node::Protected) { + bracketed += "protected"; + } + else if (func->access() == Node::Private) { + bracketed += "private"; + } + + if (func->metaness() == FunctionNode::Signal) { + bracketed += "signal"; + } + else if (func->metaness() == FunctionNode::Slot) { + bracketed += "slot"; + } + if (!bracketed.isEmpty()) + extra += " [" + bracketed.join(" ") + "]"; + } + break; + case Node::Enum: + enume = static_cast<const EnumNode *>(node); + synopsis = "enum " + name; + if (style == Summary) { + synopsis += " { "; + + QStringList documentedItems = enume->doc().enumItemNames(); + if (documentedItems.isEmpty()) { + foreach (const EnumItem &item, enume->items()) + documentedItems << item.name(); + } + QStringList omitItems = enume->doc().omitEnumItemNames(); + foreach (const QString &item, omitItems) + documentedItems.removeAll(item); + + if (documentedItems.size() <= MaxEnumValues) { + for (int i = 0; i < documentedItems.size(); ++i) { + if (i != 0) + synopsis += ", "; + synopsis += documentedItems.at(i); + } + } + else { + for (int i = 0; i < documentedItems.size(); ++i) { + if (i < MaxEnumValues-2 || i == documentedItems.size()-1) { + if (i != 0) + synopsis += ", "; + synopsis += documentedItems.at(i); + } + else if (i == MaxEnumValues - 1) { + synopsis += ", ..."; + } + } + } + if (!documentedItems.isEmpty()) + synopsis += " "; + synopsis += "}"; + } + break; + case Node::Typedef: + typedeff = static_cast<const TypedefNode *>(node); + if (typedeff->associatedEnum()) { + synopsis = "flags " + name; + } + else { + synopsis = "typedef " + name; + } + break; + case Node::Property: + property = static_cast<const PropertyNode *>(node); + synopsis = name + " : " + typified(property->qualifiedDataType()); + break; + case Node::Variable: + variable = static_cast<const VariableNode *>(node); + if (style == SeparateList) { + synopsis = name + " : " + typified(variable->dataType()); + } + else { + synopsis = typified(variable->leftType()) + " " + + name + protect(variable->rightType()); + } + break; + default: + synopsis = name; + } + + if (style == Summary) { + if (node->status() == Node::Preliminary) { + extra += " (preliminary)"; + } + else if (node->status() == Node::Deprecated) { + extra += " (deprecated)"; + } + else if (node->status() == Node::Obsolete) { + extra += " (obsolete)"; + } + } + + if (!extra.isEmpty()) { + extra.prepend("<@extra>"); + extra.append("</@extra>"); + } + return synopsis + extra; +} + +#ifdef QDOC_QML +/*! + */ +QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) +{ + QString name = taggedQmlNode(node); + if (summary) { + name = linkTag(node,name); + } + name = "<@name>" + name + "</@name>"; + QString synopsis = name; + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node); + synopsis += " : " + typified(pn->dataType()); + } + + QString extra; + if (summary) { + if (node->status() == Node::Preliminary) { + extra += " (preliminary)"; + } + else if (node->status() == Node::Deprecated) { + extra += " (deprecated)"; + } + else if (node->status() == Node::Obsolete) { + extra += " (obsolete)"; + } + } + + if (!extra.isEmpty()) { + extra.prepend("<@extra>"); + extra.append("</@extra>"); + } + return synopsis + extra; +} +#endif + +QString CppCodeMarker::markedUpName(const Node *node) +{ + QString name = linkTag(node, taggedNode(node)); + if (node->type() == Node::Function) + name += "()"; + return name; +} + +QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative) +{ + if (node->name().isEmpty()) { + return "global"; + } + else { + QString fullName; + for (;;) { + fullName.prepend(markedUpName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("<@op>::</@op>"); + node = node->parent(); + } + return fullName; + } +} + +QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, + const Node *relative) +{ + const Node *node = relative->parent(); + QString fullName; + while (node->parent()) { + fullName.prepend(markedUpName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("<@op>::</@op>"); + node = node->parent(); + } + if (!fullName.isEmpty()) + fullName.append("<@op>::</@op>"); + fullName.append(enumValue); + return fullName; +} + +QString CppCodeMarker::markedUpIncludes(const QStringList& includes) +{ + QString code; + + QStringList::ConstIterator inc = includes.begin(); + while (inc != includes.end()) { + code += "#include <<@headerfile>" + *inc + "</@headerfile>>\n"; + ++inc; + } + return addMarkUp(code, 0, ""); +} + +QString CppCodeMarker::functionBeginRegExp(const QString& funcName) +{ + return "^" + QRegExp::escape(funcName) + "$"; + +} + +QString CppCodeMarker::functionEndRegExp(const QString& /* funcName */) +{ + return "^\\}$"; +} + +#if 0 + FastSection privateReimpFuncs(classe, + "Private Reimplemented Functions", + "private reimplemented function", + "private reimplemented functions"); + FastSection protectedReimpFuncs(classe, + "Protected Reimplemented Functions", + "protected reimplemented function", + "protected reimplemented functions"); + FastSection publicReimpFuncs(classe, + "Public Reimplemented Functions", + "public reimplemented function", + "public reimplemented functions"); +#endif + +QList<Section> CppCodeMarker::sections(const InnerNode *inner, + SynopsisStyle style, + Status status) +{ + QList<Section> sections; + + if (inner->type() == Node::Class) { + const ClassNode *classe = static_cast<const ClassNode *>(inner); + + if (style == Summary) { + FastSection privateFunctions(classe, + "Private Functions", + "private function", + "private functions"); + FastSection privateSlots(classe, "Private Slots", "private slot", "private slots"); + FastSection privateTypes(classe, "Private Types", "private type", "private types"); + FastSection protectedFunctions(classe, + "Protected Functions", + "protected function", + "protected functions"); + FastSection protectedSlots(classe, + "Protected Slots", + "protected slot", + "protected slots"); + FastSection protectedTypes(classe, + "Protected Types", + "protected type", + "protected types"); + FastSection protectedVariables(classe, + "Protected Variables", + "protected type", + "protected variables"); + FastSection publicFunctions(classe, + "Public Functions", + "public function", + "public functions"); + FastSection publicSignals(classe, "Signals", "signal", "signals"); + FastSection publicSlots(classe, "Public Slots", "public slot", "public slots"); + FastSection publicTypes(classe, "Public Types", "public type", "public types"); + FastSection publicVariables(classe, + "Public Variables", + "public type", + "public variables"); + FastSection properties(classe, "Properties", "property", "properties"); + FastSection relatedNonMembers(classe, + "Related Non-Members", + "related non-member", + "related non-members"); + FastSection staticPrivateMembers(classe, + "Static Private Members", + "static private member", + "static private members"); + FastSection staticProtectedMembers(classe, + "Static Protected Members", + "static protected member", + "static protected members"); + FastSection staticPublicMembers(classe, + "Static Public Members", + "static public member", + "static public members"); + FastSection macros(inner, "Macros", "macro", "macros"); + + NodeList::ConstIterator r = classe->relatedNodes().begin(); + while (r != classe->relatedNodes().end()) { + if ((*r)->type() == Node::Function) { + FunctionNode *func = static_cast<FunctionNode *>(*r); + if (func->isMacro()) + insert(macros, *r, style, status); + else + insert(relatedNonMembers, *r, style, status); + } + else { + insert(relatedNonMembers, *r, style, status); + } + ++r; + } + + QStack<const ClassNode *> stack; + stack.push(classe); + + while (!stack.isEmpty()) { + const ClassNode *ancestorClass = stack.pop(); + + NodeList::ConstIterator c = ancestorClass->childNodes().begin(); + while (c != ancestorClass->childNodes().end()) { + bool isSlot = false; + bool isSignal = false; + bool isStatic = false; + if ((*c)->type() == Node::Function) { + const FunctionNode *func = (const FunctionNode *) *c; + isSlot = (func->metaness() == FunctionNode::Slot); + isSignal = (func->metaness() == FunctionNode::Signal); + isStatic = func->isStatic(); + } + else if ((*c)->type() == Node::Variable) { + const VariableNode *var = static_cast<const VariableNode *>(*c); + isStatic = var->isStatic(); + } + + switch ((*c)->access()) { + case Node::Public: + if (isSlot) { + insert(publicSlots, *c, style, status); + } + else if (isSignal) { + insert(publicSignals, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticPublicMembers,*c,style,status); + } + else if ((*c)->type() == Node::Property) { + insert(properties, *c, style, status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(publicVariables, *c, style, status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(publicFunctions,*c,status)) + insert(publicFunctions, *c, style, status); + } + else { + insert(publicTypes, *c, style, status); + } + break; + case Node::Protected: + if (isSlot) { + insert(protectedSlots, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticProtectedMembers,*c,style,status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(protectedVariables,*c,style,status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(protectedFunctions,*c,status)) + insert(protectedFunctions, *c, style, status); + } + else { + insert(protectedTypes, *c, style, status); + } + break; + case Node::Private: + if (isSlot) { + insert(privateSlots, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticPrivateMembers,*c,style,status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(privateFunctions,*c,status)) + insert(privateFunctions, *c, style, status); + } + else { + insert(privateTypes,*c,style,status); + } + } + ++c; + } + + QList<RelatedClass>::ConstIterator r = + ancestorClass->baseClasses().begin(); + while (r != ancestorClass->baseClasses().end()) { + stack.prepend((*r).node); + ++r; + } + } + + append(sections, publicTypes); + append(sections, properties); + append(sections, publicFunctions); + append(sections, publicSlots); + append(sections, publicSignals); + append(sections, publicVariables); + append(sections, staticPublicMembers); + append(sections, protectedTypes); + append(sections, protectedFunctions); + append(sections, protectedSlots); + append(sections, protectedVariables); + append(sections, staticProtectedMembers); + append(sections, privateTypes); + append(sections, privateFunctions); + append(sections, privateSlots); + append(sections, staticPrivateMembers); + append(sections, relatedNonMembers); + append(sections, macros); + } + else if (style == Detailed) { + FastSection memberFunctions(classe,"Member Function Documentation"); + FastSection memberTypes(classe,"Member Type Documentation"); + FastSection memberVariables(classe,"Member Variable Documentation"); + FastSection properties(classe,"Property Documentation"); + FastSection relatedNonMembers(classe,"Related Non-Members"); + FastSection macros(classe,"Macro Documentation"); + + NodeList::ConstIterator r = classe->relatedNodes().begin(); + while (r != classe->relatedNodes().end()) { + if ((*r)->type() == Node::Function) { + FunctionNode *func = static_cast<FunctionNode *>(*r); + if (func->isMacro()) + insert(macros, *r, style, status); + else + insert(relatedNonMembers, *r, style, status); + } + else { + insert(relatedNonMembers, *r, style, status); + } + ++r; + } + + NodeList::ConstIterator c = classe->childNodes().begin(); + while (c != classe->childNodes().end()) { + if ((*c)->type() == Node::Enum || + (*c)->type() == Node::Typedef) { + insert(memberTypes, *c, style, status); + } + else if ((*c)->type() == Node::Property) { + insert(properties, *c, style, status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(memberVariables, *c, style, status); + } + else if ((*c)->type() == Node::Function) { + FunctionNode *function = static_cast<FunctionNode *>(*c); + if (!function->associatedProperty()) + insert(memberFunctions, function, style, status); + } + ++c; + } + + append(sections, memberTypes); + append(sections, properties); + append(sections, memberFunctions); + append(sections, memberVariables); + append(sections, relatedNonMembers); + append(sections, macros); + } + else { + FastSection all(classe); + + QStack<const ClassNode *> stack; + stack.push(classe); + + while (!stack.isEmpty()) { + const ClassNode *ancestorClass = stack.pop(); + + NodeList::ConstIterator c = ancestorClass->childNodes().begin(); + while (c != ancestorClass->childNodes().end()) { + if ((*c)->access() != Node::Private && + (*c)->type() != Node::Property) + insert(all, *c, style, status); + ++c; + } + + QList<RelatedClass>::ConstIterator r = + ancestorClass->baseClasses().begin(); + while (r != ancestorClass->baseClasses().end()) { + stack.prepend((*r).node); + ++r; + } + } + append(sections, all); + } + } + else { + if (style == Summary || style == Detailed) { + FastSection namespaces(inner, + "Namespaces", + "namespace", + "namespaces"); + FastSection classes(inner, + "Classes", + "class", + "classes"); + FastSection types(inner, + style == Summary ? + "Types" : "Type Documentation", + "type", + "types"); + FastSection functions(inner, + style == Summary ? + "Functions" : "Function Documentation", + "function", + "functions"); + FastSection macros(inner, + style == Summary ? + "Macros" : "Macro Documentation", + "macro", + "macros"); + + NodeList nodeList = inner->childNodes(); + nodeList += inner->relatedNodes(); + + NodeList::ConstIterator n = nodeList.begin(); + while (n != nodeList.end()) { + switch ((*n)->type()) { + case Node::Namespace: + insert(namespaces, *n, style, status); + break; + case Node::Class: + insert(classes, *n, style, status); + break; + case Node::Enum: + case Node::Typedef: + insert(types, *n, style, status); + break; + case Node::Function: + { + FunctionNode *func = static_cast<FunctionNode *>(*n); + if (func->isMacro()) + insert(macros, *n, style, status); + else + insert(functions, *n, style, status); + } + break; + default: + ; + } + ++n; + } + append(sections, namespaces); + append(sections, classes); + append(sections, types); + append(sections, functions); + append(sections, macros); + } + } + + return sections; +} + +const Node *CppCodeMarker::resolveTarget(const QString &target, + const Tree *tree, + const Node *relative) +{ + if (target.endsWith("()")) { + const FunctionNode *func; + QString funcName = target; + funcName.chop(2); + + QStringList path = funcName.split("::"); + if ((func = tree->findFunctionNode(path, + relative, + Tree::SearchBaseClasses)) + && func->metaness() != FunctionNode::MacroWithoutParams) + return func; + } + else if (target.contains("#")) { + // ### this doesn't belong here; get rid of TargetNode hack + int hashAt = target.indexOf("#"); + QString link = target.left(hashAt); + QString ref = target.mid(hashAt + 1); + const Node *node; + if (link.isEmpty()) { + node = relative; + } + else { + QStringList path(link); + node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses); + } + if (node && node->isInnerNode()) { + const Atom *atom = node->doc().body().firstAtom(); + while (atom) { + if (atom->type() == Atom::Target && atom->string() == ref) { + Node *parentNode = const_cast<Node *>(node); + return new TargetNode(static_cast<InnerNode*>(parentNode), + ref); + } + atom = atom->next(); + } + } + } + else { + QStringList path = target.split("::"); + const Node *node; + if ((node = tree->findNode(path, + relative, + Tree::SearchBaseClasses | + Tree::SearchEnumValues | + Tree::NonFunction))) + return node; + } + return 0; +} + +QString CppCodeMarker::addMarkUp(const QString& protectedCode, + const Node * /* relative */, + const QString& /* dirPath */) +{ + static QRegExp globalInclude("#include +<([^<>&]+)>"); + static QRegExp yHasTypeX("(?:^|\n *)([a-zA-Z_][a-zA-Z_0-9]*)" + "(?:<[^;{}]+>)?(?: *(?:\\*|&) *| +)" + "([a-zA-Z_][a-zA-Z_0-9]*)? *[,;()=]"); + static QRegExp xNewY("([a-zA-Z_][a-zA-Z_0-9]*) *= *new +([a-zA-Z_0-9]+)"); + static QRegExp xDotY("\\b([a-zA-Z_][a-zA-Z_0-9]*) *(?:\\.|->|,[ \n]*S(?:IGNAL|LOT)\\() *" + "([a-zA-Z_][a-zA-Z_0-9]*)(?= *\\()"); + static QRegExp xIsStaticZOfY("[\n:;{(=] *(([a-zA-Z_0-9]+)::([a-zA-Z_0-9]+))(?= *\\()"); + static QRegExp classX("[:,][ \n]*(?:p(?:ublic|r(?:otected|ivate))[ \n]+)?" + "([a-zA-Z_][a-zA-Z_0-9]*)"); + static QRegExp globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\("); + static QRegExp multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)"); + multiLineComment.setMinimal(true); + static QRegExp singleLineComment("//(?!!)[^!\n]*"); + static QRegExp preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define" + "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)"); + static QRegExp literals(""(?:[^\\\\&]|\\\\[^\n]|&(?!quot;))*"" + "|'(?:[^\\\\]|\\\\(?:[^x0-9']|x[0-9a-f]{1,4}|[0-9]{1,3}))'"); + + QString result = protectedCode; + int pos; + + if (!hurryUp()) { + /* + Mark global includes. For example: + + #include <<@headerfile>QString</@headerfile> + */ + pos = 0; + while ((pos = result.indexOf(globalInclude, pos)) != -1) + pos += globalInclude.matchedLength() + + insertTagAround(result, + globalInclude.pos(1), + globalInclude.cap(1).length(), + "@headerfile"); + + /* + Look for variable definitions and similar constructs, mark + the data type, and remember the type of the variable. + */ + QMap<QString, QSet<QString> > typesForVariable; + pos = 0; + while ((pos = yHasTypeX.indexIn(result, pos)) != -1) { + QString x = yHasTypeX.cap(1); + QString y = yHasTypeX.cap(2); + + if (!y.isEmpty()) + typesForVariable[y].insert(x); + + /* + Without the minus one at the end, 'void member(Class + var)' would give 'member' as a variable of type 'void', + but would ignore 'Class var'. (### Is that true?) + */ + pos += yHasTypeX.matchedLength() + + insertTagAround(result, + yHasTypeX.pos(1), + x.length(), + "@type") - 1; + } + + /* + Do syntax highlighting of preprocessor directives. + */ + pos = 0; + while ((pos = preprocessor.indexIn(result, pos)) != -1) + pos += preprocessor.matchedLength() + + insertTagAround(result, + preprocessor.pos(1), + preprocessor.cap(1).length(), + "@preprocessor"); + + /* + Deal with string and character literals. + */ + pos = 0; + while ((pos = literals.indexIn(result, pos)) != -1) + pos += literals.matchedLength() + + insertTagAround(result, + pos, + literals.matchedLength(), + result.at(pos) == + QLatin1Char(' ') ? "@string" : "@char"); + + /* + Look for 'var = new Class'. + */ + pos = 0; + while ((pos = xNewY.indexIn(result, pos)) != -1) { + QString x = xNewY.cap(1); + QString y = xNewY.cap(2); + typesForVariable[x].insert(y); + + pos += xNewY.matchedLength() + insertTagAround(result, + xNewY.pos(2), + y.length(), + "@type"); + } + + /* + Insert some stuff that cannot harm. + */ + typesForVariable["qApp"].insert("QApplication"); + + /* + Add link to ': Class'. + */ + pos = 0; + while ((pos = classX.indexIn(result, pos)) != -1) + pos += classX.matchedLength() + + insertTagAround(result, + classX.pos(1), + classX.cap(1).length(), + "@type") - 1; + + /* + Find use of any of + + var.method() + var->method() + var, SIGNAL(method()) + var, SLOT(method()). + */ + pos = 0; + while ((pos = xDotY.indexIn(result, pos)) != -1) { + QString x = xDotY.cap(1); + QString y = xDotY.cap(2); + + QSet<QString> types = typesForVariable.value(x); + pos += xDotY.matchedLength() + + insertTagAround(result, + xDotY.pos(2), + xDotY.cap(2).length(), + "@func", + (types.count() == 1) ? "target=\"" + + protect(*types.begin() + "::" + y) + + "()\"" : QString()); + } + + /* + Add link to 'Class::method()'. + */ + pos = 0; + while ((pos = xIsStaticZOfY.indexIn(result, pos)) != -1) { + QString x = xIsStaticZOfY.cap(1); + QString z = xIsStaticZOfY.cap(3); + + pos += insertTagAround(result, + xIsStaticZOfY.pos(3), + z.length(), + "@func", + "target=\"" + protect(x) + "()\""); + pos += insertTagAround(result, + xIsStaticZOfY.pos(2), + xIsStaticZOfY.cap(2).length(), + "@type"); + pos += xIsStaticZOfY.matchedLength() - 1; + } + + /* + Add link to 'globalFunction()'. + */ + pos = 0; + while ((pos = globalX.indexIn(result, pos)) != -1) { + QString x = globalX.cap(1); + if (x != "QT_FORWARD_DECLARE_CLASS") { + pos += globalX.matchedLength() + + insertTagAround(result, + globalX.pos(1), + x.length(), + "@func", + "target=\"" + protect(x) + "()\"") - 1; + } + else + pos += globalX.matchedLength(); + } + } + + /* + Do syntax highlighting of comments. Also alter the code in a + minor way, so that we can include comments in documentation + comments. + */ + pos = 0; + while (pos != -1) { + int mlpos; + int slpos; + int len; + slpos = singleLineComment.indexIn(result, pos); + mlpos = multiLineComment.indexIn(result, pos); + + if (slpos == -1 && mlpos == -1) + break; + + if (slpos == -1) { + pos = mlpos; + len = multiLineComment.matchedLength(); + } + else if (mlpos == -1) { + pos = slpos; + len = singleLineComment.matchedLength(); + } + else { + if (slpos < mlpos) { + pos = slpos; + len = singleLineComment.matchedLength(); + } + else { + pos = mlpos; + len = multiLineComment.matchedLength(); + } + } + + if (result.at(pos + 1) == QLatin1Char(' ')) { + result.remove(pos + len - 2, 1); + result.remove(pos + 1, 1); + len -= 2; + + forever { + int endcodePos = result.indexOf("\\ endcode", pos); + if (endcodePos == -1 || endcodePos >= pos + len) + break; + result.remove(endcodePos + 1, 1); + len -= 1; + } + } + pos += len + insertTagAround(result, pos, len, "@comment"); + } + + return result; +} + +#ifdef QDOC_QML +/*! + This function is for documenting QML properties. It returns + the list of documentation sections for the children of the + \a qmlClassNode. + + Currently, it only handles QML property groups. + */ +QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style) +{ + QList<Section> sections; + if (qmlClassNode) { + if (style == Summary) { + FastSection qmlproperties(qmlClassNode, + "Properties", + "property", + "properties"); + FastSection qmlsignals(qmlClassNode, + "Signals", + "signal", + "signals"); + FastSection qmlmethods(qmlClassNode, + "Methods", + "method", + "methods"); + + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c); + NodeList::ConstIterator p = qpgn->childNodes().begin(); + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + insert(qmlproperties,*p,style,Okay); + } + ++p; + } + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + else if (style == Detailed) { + FastSection qmlproperties(qmlClassNode, "Property Documentation"); + FastSection qmlsignals(qmlClassNode,"Signal Documentation"); + FastSection qmlmethods(qmlClassNode,"Method Documentation"); + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + insert(qmlproperties,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + } + + return sections; +} +#endif + +QT_END_NAMESPACE diff --git a/tools/qdoc3/qmlcodemarker.h b/tools/qdoc3/qmlcodemarker.h new file mode 100644 index 0000000..8c83c04 --- /dev/null +++ b/tools/qdoc3/qmlcodemarker.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications 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$ +** +****************************************************************************/ + +/* + cppcodemarker.h +*/ + +#ifndef CPPCODEMARKER_H +#define CPPCODEMARKER_H + +#include "codemarker.h" + +QT_BEGIN_NAMESPACE + +class CppCodeMarker : public CodeMarker +{ + public: + CppCodeMarker(); + ~CppCodeMarker(); + + bool recognizeCode(const QString& code); + bool recognizeExtension(const QString& ext); + bool recognizeLanguage(const QString& lang); + QString plainName(const Node *node); + QString plainFullName(const Node *node, const Node *relative); + QString markedUpCode(const QString& code, + const Node *relative, + const QString& dirPath); + QString markedUpSynopsis(const Node *node, + const Node *relative, + SynopsisStyle style); +#ifdef QDOC_QML + QString markedUpQmlItem(const Node *node, bool summary); +#endif + QString markedUpName(const Node *node); + QString markedUpFullName(const Node *node, const Node *relative); + QString markedUpEnumValue(const QString &enumValue, const Node *relative); + QString markedUpIncludes(const QStringList& includes); + QString functionBeginRegExp(const QString& funcName); + QString functionEndRegExp(const QString& funcName); + QList<Section> sections(const InnerNode *innerNode, + SynopsisStyle style, + Status status); + QList<Section> qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style); + const Node *resolveTarget(const QString& target, + const Tree *tree, + const Node *relative); + +private: + QString addMarkUp(const QString& protectedCode, + const Node *relative, + const QString& dirPath); +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qmldebugger/expressionquerywidget.cpp b/tools/qmldebugger/expressionquerywidget.cpp new file mode 100644 index 0000000..b29b465 --- /dev/null +++ b/tools/qmldebugger/expressionquerywidget.cpp @@ -0,0 +1,216 @@ +#include <QtGui/qlabel.h> +#include <QtGui/qtextedit.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qevent.h> +#include <QtGui/qgroupbox.h> +#include <QtGui/qtextobject.h> +#include <QtGui/qlayout.h> + +#include "expressionquerywidget.h" + +ExpressionQueryWidget::ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent) + : QWidget(parent), + m_style(Compact), + m_client(client), + m_query(0), + m_groupBox(0), + m_textEdit(new QTextEdit), + m_lineEdit(0), + m_button(0) +{ + m_prompt = QLatin1String(">> "); + + m_groupBox = new QGroupBox; + QVBoxLayout *vbox = new QVBoxLayout(m_groupBox); + vbox->addWidget(m_textEdit); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(m_groupBox); + + updateTitle(); + + if (m_style == Compact) { + QHBoxLayout *hbox = new QHBoxLayout; + m_button = new QPushButton(tr("Execute")); + m_button->setEnabled(false); + connect(m_button, SIGNAL(clicked()), SLOT(executeExpression())); + m_lineEdit = new QLineEdit; + connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression())); + connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(lineEditTextChanged(QString))); + hbox->addWidget(new QLabel(tr("Expression:"))); + hbox->addWidget(m_lineEdit); + hbox->addWidget(m_button); + vbox->addLayout(hbox); + + m_textEdit->setReadOnly(true); + m_lineEdit->installEventFilter(this); + } else { + m_textEdit->installEventFilter(this); + } +} + +void ExpressionQueryWidget::updateTitle() +{ + if (m_currObject.debugId() < 0) { + m_groupBox->setTitle(tr("Expression queries")); + } else { + QString desc = QLatin1String("<") + + m_currObject.className() + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name()) + + QLatin1String(">"); + m_groupBox->setTitle(tr("Expression queries (using context for %1)" + , "Selected object").arg(desc)); + } +} + +void ExpressionQueryWidget::appendPrompt() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_style == Compact) { + m_textEdit->insertPlainText("\n"); + } else { + m_textEdit->setTextColor(Qt::gray); + m_textEdit->append(m_prompt); + } +} + +void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj) +{ + m_currObject = obj; + updateTitle(); +} + +void ExpressionQueryWidget::checkCurrentContext() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId()) + showCurrentContext(); + m_objectAtLastFocus = m_currObject; +} + +void ExpressionQueryWidget::showCurrentContext() +{ + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::darkGreen); + m_textEdit->append(m_currObject.className() + + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name())); + appendPrompt(); +} + +void ExpressionQueryWidget::executeExpression() +{ + if (m_style == Compact) + m_expr = m_lineEdit->text().trimmed(); + else + m_expr = m_expr.trimmed(); + + if (!m_expr.isEmpty() && m_currObject.debugId() != -1) { + if (m_query) + delete m_query; + m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this); + if (!m_query->isWaiting()) + showResult(); + else + QObject::connect(m_query, SIGNAL(stateChanged(State)), + this, SLOT(showResult())); + + m_lastExpr = m_expr; + if (m_lineEdit) + m_lineEdit->clear(); + } +} + +void ExpressionQueryWidget::showResult() +{ + if (m_query) { + m_textEdit->moveCursor(QTextCursor::End); + QString result; + if (m_query->result().isNull()) + result = QLatin1String("<no value>"); + else + result = m_query->result().toString(); + + if (m_style == Compact) { + m_textEdit->setTextColor(Qt::black); + m_textEdit->setFontWeight(QFont::Bold); + m_textEdit->insertPlainText(m_expr + " : "); + m_textEdit->setFontWeight(QFont::Normal); + m_textEdit->insertPlainText(result); + } else { + m_textEdit->append(result); + } + appendPrompt(); + m_expr.clear(); + } +} + +void ExpressionQueryWidget::lineEditTextChanged(const QString &s) +{ + if (m_button) + m_button->setEnabled(!s.isEmpty()); +} + +bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_textEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + int key = keyEvent->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter) { + executeExpression(); + return true; + } else if (key == Qt::Key_Backspace) { + // ensure m_expr doesn't contain backspace characters + QTextCursor cursor = m_textEdit->textCursor(); + bool atLastLine = !(cursor.block().next().isValid()); + if (!atLastLine) + return true; + if (cursor.columnNumber() <= m_prompt.count()) + return true; + cursor.deletePreviousChar(); + m_expr = cursor.block().text().mid(m_prompt.count()); + return true; + } else { + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::black); + m_expr += keyEvent->text(); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + m_textEdit->moveCursor(QTextCursor::End); + break; + default: + break; + } + } else if (obj == m_lineEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + int key = keyEvent->key(); + if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) { + m_expr = m_lineEdit->text(); + if (!m_lastExpr.isEmpty()) + m_lineEdit->setText(m_lastExpr); + } else if (key == Qt::Key_Down) { + m_lineEdit->setText(m_expr); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + break; + default: + break; + } + } + return QWidget::eventFilter(obj, event); +} diff --git a/tools/qmldebugger/expressionquerywidget.h b/tools/qmldebugger/expressionquerywidget.h new file mode 100644 index 0000000..8db8f9f --- /dev/null +++ b/tools/qmldebugger/expressionquerywidget.h @@ -0,0 +1,62 @@ +#ifndef EXPRESSIONQUERYWIDGET_H +#define EXPRESSIONQUERYWIDGET_H + +#include <QWidget> + +#include <QtDeclarative/qmldebug.h> + +QT_BEGIN_NAMESPACE + +class QGroupBox; +class QTextEdit; +class QLineEdit; +class QPushButton; + +class ExpressionQueryWidget : public QWidget +{ + Q_OBJECT +public: + enum Style { + Compact, + Shell + }; + + ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent = 0); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +public slots: + void setCurrentObject(const QmlDebugObjectReference &obj); + +private slots: + void executeExpression(); + void showResult(); + void lineEditTextChanged(const QString &s); + +private: + void appendPrompt(); + void checkCurrentContext(); + void showCurrentContext(); + void updateTitle(); + + Style m_style; + + QmlEngineDebug *m_client; + QmlDebugExpressionQuery *m_query; + QGroupBox *m_groupBox; + QTextEdit *m_textEdit; + QLineEdit *m_lineEdit; + QPushButton *m_button; + QString m_prompt; + QString m_expr; + QString m_lastExpr; + + QmlDebugObjectReference m_currObject; + QmlDebugObjectReference m_objectAtLastFocus; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/tools/qmldebugger/objectpropertiesview.cpp b/tools/qmldebugger/objectpropertiesview.cpp index f725194..61afe3f 100644 --- a/tools/qmldebugger/objectpropertiesview.cpp +++ b/tools/qmldebugger/objectpropertiesview.cpp @@ -22,12 +22,12 @@ public: }; PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget) -: QTreeWidgetItem(widget) + : QTreeWidgetItem(widget) { } PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent) -: QTreeWidgetItem(parent) + : QTreeWidgetItem(parent) { } @@ -108,8 +108,10 @@ void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) item->setText(0, p.name()); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - if (!p.hasNotifySignal()) - item->setForeground(0, Qt::lightGray); + if (!p.hasNotifySignal()) { + item->setForeground(0, Qt::gray); + item->setForeground(1, Qt::gray); + } if (!p.binding().isEmpty()) { PropertiesViewItem *binding = new PropertiesViewItem(item); @@ -159,15 +161,22 @@ void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant & { for (int i=0; i<m_tree->topLevelItemCount(); i++) { PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i)); - if (item->property.name() == name) - item->setText(1, value.toString()); + if (item->property.name() == name) { + if (value.isNull()) { + item->setText(1, QLatin1String("<null>") + + QLatin1String(" : ") + + item->property.valueTypeName()); + } else { + item->setText(1, value.toString()); + } + } } } void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i) { PropertiesViewItem *item = static_cast<PropertiesViewItem *>(i); - if (!item->property.name().isEmpty() && item->property.hasNotifySignal()) + if (!item->property.name().isEmpty()) emit activated(m_object, item->property); } diff --git a/tools/qmldebugger/objecttree.cpp b/tools/qmldebugger/objecttree.cpp index f68e7f1..0b92ceb 100644 --- a/tools/qmldebugger/objecttree.cpp +++ b/tools/qmldebugger/objecttree.cpp @@ -19,8 +19,8 @@ ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent) { setHeaderHidden(true); - connect(this, SIGNAL(itemClicked(QTreeWidgetItem *, int)), - this, SLOT(handleItemClicked(QTreeWidgetItem *))); + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(currentItemChanged(QTreeWidgetItem *))); } void ObjectTree::reload(int objectDebugId) @@ -38,7 +38,7 @@ void ObjectTree::reload(int objectDebugId) this, SLOT(objectFetched())); } -void ObjectTree::selectObject(int debugId) +void ObjectTree::setCurrentObject(int debugId) { QTreeWidgetItem *item = findItemByObjectId(debugId); if (item) { @@ -57,14 +57,14 @@ void ObjectTree::objectFetched() m_query = 0; } -void ObjectTree::handleItemClicked(QTreeWidgetItem *item) +void ObjectTree::currentItemChanged(QTreeWidgetItem *item) { QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); if (obj.debugId() < 0) { qWarning("QML Object Tree: bad object id"); return; } - emit objectSelected(obj); + emit currentObjectChanged(obj); } void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent) diff --git a/tools/qmldebugger/objecttree.h b/tools/qmldebugger/objecttree.h index bba6c08..3c0a5c6 100644 --- a/tools/qmldebugger/objecttree.h +++ b/tools/qmldebugger/objecttree.h @@ -20,19 +20,19 @@ public: ObjectTree(QmlEngineDebug *client, QWidget *parent = 0); signals: - void objectSelected(const QmlDebugObjectReference &); + void currentObjectChanged(const QmlDebugObjectReference &); void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); public slots: void reload(int objectDebugId); - void selectObject(int debugId); + void setCurrentObject(int debugId); protected: virtual void mousePressEvent(QMouseEvent *); private slots: void objectFetched(); - void handleItemClicked(QTreeWidgetItem *); + void currentItemChanged(QTreeWidgetItem *); private: QTreeWidgetItem *findItemByObjectId(int debugId) const; diff --git a/tools/qmldebugger/qmldebugger.cpp b/tools/qmldebugger/qmldebugger.cpp index 0f0fc03..e0a76b6 100644 --- a/tools/qmldebugger/qmldebugger.cpp +++ b/tools/qmldebugger/qmldebugger.cpp @@ -57,6 +57,10 @@ QmlDebugger::QmlDebugger(QWidget *parent) QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError))); + + + m_tabs->setCurrentIndex(1); + connectToHost(); } void QmlDebugger::setHost(const QString &host) diff --git a/tools/qmldebugger/qmldebugger.pri b/tools/qmldebugger/qmldebugger.pri index ce36381..c49d334 100644 --- a/tools/qmldebugger/qmldebugger.pri +++ b/tools/qmldebugger/qmldebugger.pri @@ -7,7 +7,8 @@ HEADERS += $$PWD/qmldebugger.h \ $$PWD/watchtable.h \ $$PWD/engine.h \ $$PWD/objecttree.h \ - $$PWD/objectpropertiesview.h + $$PWD/objectpropertiesview.h \ + $$PWD/expressionquerywidget.h SOURCES += $$PWD/qmldebugger.cpp \ $$PWD/main.cpp \ @@ -15,7 +16,8 @@ SOURCES += $$PWD/qmldebugger.cpp \ $$PWD/watchtable.cpp \ $$PWD/engine.cpp \ $$PWD/objecttree.cpp \ - $$PWD/objectpropertiesview.cpp + $$PWD/objectpropertiesview.cpp \ + $$PWD/expressionquerywidget.cpp RESOURCES += $$PWD/qmldebugger.qrc diff --git a/tools/qmldebugger/watchtable.cpp b/tools/qmldebugger/watchtable.cpp index e4163dc..512bfb2 100644 --- a/tools/qmldebugger/watchtable.cpp +++ b/tools/qmldebugger/watchtable.cpp @@ -193,6 +193,9 @@ void WatchTableModel::addValue(int column, const QVariant &value) void WatchTableModel::togglePropertyWatch(const QmlDebugObjectReference &object, const QmlDebugPropertyReference &property) { + if (!property.hasNotifySignal()) + return; + QmlDebugWatch *watch = findWatch(object.debugId(), property.name()); if (watch) { // watch will be deleted in watchStateChanged() diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp index 95dfd16..60fa13a 100644 --- a/tools/qmlviewer/qmlviewer.cpp +++ b/tools/qmlviewer/qmlviewer.cpp @@ -628,6 +628,11 @@ void QmlViewer::openQml(const QString& fileName) QUrl url(fileName); QFileInfo fi(fileName); if (fi.exists()) { + if (fi.suffix().toLower() != QLatin1String("qml")) { + qWarning() << "qmlviewer cannot open non-QML file" << fileName; + return; + } + url = QUrl::fromLocalFile(fi.absoluteFilePath()); QmlContext *ctxt = canvas->rootContext(); QDir dir(fi.path()+"/dummydata", "*.qml"); @@ -656,6 +661,9 @@ void QmlViewer::openQml(const QString& fileName) dummyData->setParent(this); } } + } else { + qWarning() << "qmlviewer cannot find file:" << fileName; + return; } canvas->setUrl(url); |