qdoc: Allow documenting a C++ class as a QML type.

Now qdoc can handle the case where a C++ class is
documented as a QML type of the same name, or as
both a C++ class and a QML type of the same name.

And collisions pages are created for both the HTML
and the DITA XML output. A collision page is created
when two items have the same name. The collision
pages will be augmented later to include the list
of pages where ambiguous links to one of the items
listed on the collision page are actually located,
so the writer can go back to those links and add
the appropriate qualifier.

Change-Id: I5a9632b2d2209e0784392047056bed8962005624
Reviewed-by: Martin Smith <martin.smith@nokia.com>
Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
This commit is contained in:
Martin Smith 2012-03-30 13:43:46 +02:00 committed by Qt by Nokia
parent f733a0044e
commit 9b0c0823c0
15 changed files with 997 additions and 728 deletions

View File

@ -649,7 +649,6 @@ QStringList CodeMarker::macRefsForNode(Node *node)
} }
case Node::Namespace: case Node::Namespace:
case Node::Fake: case Node::Fake:
case Node::Target:
default: default:
return QStringList(); return QStringList();
} }

View File

@ -826,61 +826,38 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
return sections; return sections;
} }
/*!
Search the \a tree for a node named \a target
*/
const Node *CppCodeMarker::resolveTarget(const QString& target, const Node *CppCodeMarker::resolveTarget(const QString& target,
const Tree* tree, const Tree* tree,
const Node* relative, const Node* relative,
const Node* self) const Node* self)
{ {
const Node* node = 0;
if (target.endsWith("()")) { if (target.endsWith("()")) {
const FunctionNode *func;
QString funcName = target; QString funcName = target;
funcName.chop(2); funcName.chop(2);
QStringList path = funcName.split("::"); QStringList path = funcName.split("::");
if ((func = tree->findFunctionNode(path, const FunctionNode* fn = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses);
relative, if (fn) {
Tree::SearchBaseClasses)) /*
&& func->metaness() != FunctionNode::MacroWithoutParams) Why is this case not accepted?
return func; */
if (fn->metaness() != FunctionNode::MacroWithoutParams)
node = fn;
}
} }
else if (target.contains(QLatin1Char('#'))) { else if (target.contains(QLatin1Char('#'))) {
// ### this doesn't belong here; get rid of TargetNode hack // This error message is never printed; I think we can remove the case.
int hashAt = target.indexOf(QLatin1Char('#')); qDebug() << "qdoc: target case not handled:" << target;
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 { else {
QStringList path = target.split("::"); QStringList path = target.split("::");
const Node *node; int flags = Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction;
int flags = Tree::SearchBaseClasses | node = tree->findNode(path, relative, flags, self);
Tree::SearchEnumValues |
Tree::NonFunction;
if ((node = tree->findNode(path,
relative,
flags,
self)))
return node;
} }
return 0; return node;
} }
static const char * const typeTable[] = { static const char * const typeTable[] = {

View File

@ -79,7 +79,6 @@ QT_BEGIN_NAMESPACE
#define COMMAND_PROPERTY Doc::alias("property") #define COMMAND_PROPERTY Doc::alias("property")
#define COMMAND_REIMP Doc::alias("reimp") #define COMMAND_REIMP Doc::alias("reimp")
#define COMMAND_RELATES Doc::alias("relates") #define COMMAND_RELATES Doc::alias("relates")
#define COMMAND_SERVICE Doc::alias("service")
#define COMMAND_STARTPAGE Doc::alias("startpage") #define COMMAND_STARTPAGE Doc::alias("startpage")
#define COMMAND_TYPEDEF Doc::alias("typedef") #define COMMAND_TYPEDEF Doc::alias("typedef")
#define COMMAND_VARIABLE Doc::alias("variable") #define COMMAND_VARIABLE Doc::alias("variable")
@ -119,7 +118,7 @@ QStringList CppCodeParser::exampleDirs;
This is used for fuzzy matching only, which in turn is only used This is used for fuzzy matching only, which in turn is only used
for Qt Jambi. for Qt Jambi.
*/ */
static QString cleanType(const QString &type, const Tree *tree) static QString cleanType(const QString &type, Tree* tree)
{ {
QString result = type; QString result = type;
result.replace("qlonglong", "long long"); result.replace("qlonglong", "long long");
@ -145,14 +144,13 @@ static QString cleanType(const QString &type, const Tree *tree)
while ((pos = result.indexOf(regExp, pos)) != -1) { while ((pos = result.indexOf(regExp, pos)) != -1) {
// we assume that the path for the associated enum // we assume that the path for the associated enum
// is the same as for the flag typedef // is the same as for the flag typedef
QStringList path = regExp.cap(2).split("::", QStringList path = regExp.cap(2).split("::", QString::SkipEmptyParts);
QString::SkipEmptyParts); QStringList tmpPath = QStringList(path) << regExp.cap(3);
const EnumNode *enume = static_cast<const EnumNode *>( EnumNode* en = tree->findEnumNode(tmpPath);
tree->findNode(QStringList(path) << regExp.cap(3), if (en && en->flagsType()) {
Node::Enum)); tmpPath = QStringList(path) << en->flagsType()->name();
if (enume && enume->flagsType()) result.replace(pos, regExp.matchedLength(), tmpPath.join("::"));
result.replace(pos, regExp.matchedLength(), }
(QStringList(path) << enume->flagsType()->name()).join("::"));
++pos; ++pos;
} }
} }
@ -191,9 +189,12 @@ void CppCodeParser::initializeParser(const Config &config)
{ {
CodeParser::initializeParser(config); CodeParser::initializeParser(config);
/*
All these can appear in a C++ namespace. Don't add
anything that can't be in a C++ namespace.
*/
nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace); nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace);
nodeTypeMap.insert(COMMAND_CLASS, Node::Class); nodeTypeMap.insert(COMMAND_CLASS, Node::Class);
nodeTypeMap.insert(COMMAND_SERVICE, Node::Class);
nodeTypeMap.insert(COMMAND_ENUM, Node::Enum); nodeTypeMap.insert(COMMAND_ENUM, Node::Enum);
nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef); nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef);
nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property); nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property);
@ -306,7 +307,13 @@ void CppCodeParser::parseSourceFile(const Location& location,
Tokenizer fileTokenizer(fileLocation, in); Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer; tokenizer = &fileTokenizer;
readToken(); readToken();
usedNamespaces.clear();
/*
The set of active namespaces is cleared before parsing
each source file. The word "source" here means cpp file.
*/
activeNamespaces_.clear();
matchDocsAndStuff(); matchDocsAndStuff();
in.close(); in.close();
} }
@ -403,14 +410,14 @@ const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
This is necessary because Roberto's parser resolves typedefs. This is necessary because Roberto's parser resolves typedefs.
*/ */
if (!func && fuzzy) { if (!func && fuzzy) {
func = tre->findFunctionNode(parentPath + func = tree_->findFunctionNode(parentPath +
QStringList(clone->name()), QStringList(clone->name()),
relative, relative,
flags); flags);
if (!func && clone->name().contains('_')) { if (!func && clone->name().contains('_')) {
QStringList path = parentPath; QStringList path = parentPath;
path << clone->name().split('_'); path << clone->name().split('_');
func = tre->findFunctionNode(path, relative, flags); func = tree_->findFunctionNode(path, relative, flags);
} }
if (func) { if (func) {
@ -512,7 +519,6 @@ QSet<QString> CppCodeParser::topicCommands()
<< COMMAND_NAMESPACE << COMMAND_NAMESPACE
<< COMMAND_PAGE << COMMAND_PAGE
<< COMMAND_PROPERTY << COMMAND_PROPERTY
<< COMMAND_SERVICE
<< COMMAND_TYPEDEF << COMMAND_TYPEDEF
<< COMMAND_VARIABLE << COMMAND_VARIABLE
<< COMMAND_QMLCLASS << COMMAND_QMLCLASS
@ -543,21 +549,21 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN)); doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
} }
else { else {
if (!usedNamespaces.isEmpty()) { if (!activeNamespaces_.isEmpty()) {
foreach (const QString &usedNamespace, usedNamespaces) { foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace.split("::") + parentPath; QStringList newPath = usedNamespace_.split("::") + parentPath;
func = tre->findFunctionNode(newPath, clone); func = tree_->findFunctionNode(newPath, clone);
if (func) if (func)
break; break;
} }
} }
// Search the root namespace if no match was found. // Search the root namespace if no match was found.
if (func == 0) if (func == 0)
func = tre->findFunctionNode(parentPath, clone); func = tree_->findFunctionNode(parentPath, clone);
if (func == 0) { if (func == 0) {
if (parentPath.isEmpty() && !lastPath.isEmpty()) if (parentPath.isEmpty() && !lastPath.isEmpty())
func = tre->findFunctionNode(lastPath, clone); func = tree_->findFunctionNode(lastPath, clone);
if (func == 0) { if (func == 0) {
doc.location().warning(tr("Cannot find '%1' in '\\%2'") doc.location().warning(tr("Cannot find '%1' in '\\%2'")
.arg(clone->name() + "(...)") .arg(clone->name() + "(...)")
@ -589,7 +595,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QStringList parentPath; QStringList parentPath;
FunctionNode *func = 0; FunctionNode *func = 0;
if (makeFunctionNode(arg, &parentPath, &func, tre->root())) { if (makeFunctionNode(arg, &parentPath, &func, tree_->root())) {
if (!parentPath.isEmpty()) { if (!parentPath.isEmpty()) {
doc.location().warning(tr("Invalid syntax in '\\%1'") doc.location().warning(tr("Invalid syntax in '\\%1'")
.arg(COMMAND_MACRO)); .arg(COMMAND_MACRO));
@ -610,7 +616,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return func; return func;
} }
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) { else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) {
func = new FunctionNode(tre->root(), arg); func = new FunctionNode(tree_->root(), arg);
func->setAccess(Node::Public); func->setAccess(Node::Public);
func->setLocation(doc.location()); func->setLocation(doc.location());
func->setMetaness(FunctionNode::MacroWithoutParams); func->setMetaness(FunctionNode::MacroWithoutParams);
@ -624,25 +630,45 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
} }
else if (nodeTypeMap.contains(command)) { else if (nodeTypeMap.contains(command)) {
/* /*
The command was neither "fn" nor "macro" . We should only get in here if the command refers to
something that can appear in a C++ namespace,
i.e. a class, another namespace, an enum, a typedef,
a property or a variable. I think these are handled
this way to allow the writer to refer to the entity
without including the namespace qualifier.
*/ */
// ### split(QLatin1Char(' ')) hack is there to support header file syntax Node::Type type = nodeTypeMap[command];
Node::SubType subtype = Node::NoSubType;
if (type == Node::Fake)
subtype = Node::QmlClass;
QStringList paths = arg.split(QLatin1Char(' ')); QStringList paths = arg.split(QLatin1Char(' '));
QStringList path = paths[0].split("::"); QStringList path = paths[0].split("::");
Node *node = 0; Node *node = 0;
if (!usedNamespaces.isEmpty()) {
foreach (const QString &usedNamespace, usedNamespaces) { /*
QStringList newPath = usedNamespace.split("::") + path; If the command refers to something that can be in a
node = tre->findNode(newPath, nodeTypeMap[command]); C++ namespace, search for it first in all the known
C++ namespaces.
*/
if (!activeNamespaces_.isEmpty()) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + path;
node = tree_->findNodeByNameAndType(newPath, type, subtype, 0);
if (node) { if (node) {
path = newPath; path = newPath;
break; break;
} }
} }
} }
// Search the root namespace if no match was found.
if (node == 0) /*
node = tre->findNode(path, nodeTypeMap[command]); If the node was not found in a C++ namespace, search
for it in the root namespace.
*/
if (node == 0) {
node = tree_->findNodeByNameAndType(path, type, subtype, 0);
}
if (node == 0) { if (node == 0) {
doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file") doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
@ -650,63 +676,40 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
lastPath = path; lastPath = path;
} }
else if (command == COMMAND_SERVICE) {
// If the command is "\service", then we need to tag the
// class with the actual service name.
QStringList args = arg.split(QLatin1Char(' '));
if (args.size() > 1) {
ClassNode *cnode = static_cast<ClassNode *>(node);
cnode->setServiceName(args[1]);
cnode->setHideFromMainList(true);
}
}
else if (node->isInnerNode()) { else if (node->isInnerNode()) {
/*
This treets a class as a namespace.
*/
if (path.size() > 1) { if (path.size() > 1) {
path.pop_back(); path.pop_back();
usedNamespaces.insert(path.join("::")); QString ns = path.join("::");
activeNamespaces_.insert(ns);
} }
} }
#if 0
/*
This code apparently does nothing. After further
investigation to verify it is useless, it will
be removed.
*/
if (command == COMMAND_CLASS) {
if (paths.size() > 1) {
if (!paths[1].endsWith(".h")) {
ClassNode* cnode = static_cast<ClassNode*>(node);
cnode->setQmlElement(paths[1]);
}
}
}
#endif
return node; return node;
} }
else if (command == COMMAND_EXAMPLE) { else if (command == COMMAND_EXAMPLE) {
if (Config::generateExamples) { ExampleNode* en = new ExampleNode(tree_->root(), arg);
ExampleNode* en = new ExampleNode(tre->root(), arg); createExampleFileNodes(en);
createExampleFileNodes(en); return en;
return en;
}
} }
else if (command == COMMAND_EXTERNALPAGE) { else if (command == COMMAND_EXTERNALPAGE) {
return new FakeNode(tre->root(), arg, Node::ExternalPage, Node::ArticlePage); return new FakeNode(tree_->root(), arg, Node::ExternalPage, Node::ArticlePage);
} }
else if (command == COMMAND_FILE) { else if (command == COMMAND_FILE) {
return new FakeNode(tre->root(), arg, Node::File, Node::NoPageType); return new FakeNode(tree_->root(), arg, Node::File, Node::NoPageType);
} }
else if (command == COMMAND_GROUP) { else if (command == COMMAND_GROUP) {
return new FakeNode(tre->root(), arg, Node::Group, Node::OverviewPage); return new FakeNode(tree_->root(), arg, Node::Group, Node::OverviewPage);
} }
else if (command == COMMAND_HEADERFILE) { else if (command == COMMAND_HEADERFILE) {
return new FakeNode(tre->root(), arg, Node::HeaderFile, Node::ApiPage); return new FakeNode(tree_->root(), arg, Node::HeaderFile, Node::ApiPage);
} }
else if (command == COMMAND_MODULE) { else if (command == COMMAND_MODULE) {
return new FakeNode(tre->root(), arg, Node::Module, Node::OverviewPage); return new FakeNode(tree_->root(), arg, Node::Module, Node::OverviewPage);
} }
else if (command == COMMAND_QMLMODULE) { else if (command == COMMAND_QMLMODULE) {
return new FakeNode(tre->root(), arg, Node::QmlModule, Node::OverviewPage); return new FakeNode(tree_->root(), arg, Node::QmlModule, Node::OverviewPage);
} }
else if (command == COMMAND_PAGE) { else if (command == COMMAND_PAGE) {
Node::PageType ptype = Node::ArticlePage; Node::PageType ptype = Node::ArticlePage;
@ -740,30 +743,27 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
If there is no collision, just create a new Page If there is no collision, just create a new Page
node and return that one. node and return that one.
*/ */
NameCollisionNode* ncn = tre->checkForCollision(args[0]); NameCollisionNode* ncn = tree_->checkForCollision(args[0]);
FakeNode* fn = 0; FakeNode* fn = 0;
if (ptype == Node::DitaMapPage) if (ptype == Node::DitaMapPage)
fn = new DitaMapNode(tre->root(), args[0]); fn = new DitaMapNode(tree_->root(), args[0]);
else else
fn = new FakeNode(tre->root(), args[0], Node::Page, ptype); fn = new FakeNode(tree_->root(), args[0], Node::Page, ptype);
if (ncn) { if (ncn) {
ncn->addCollision(fn); ncn->addCollision(fn);
} }
return fn; return fn;
} }
else if (command == COMMAND_DITAMAP) { else if (command == COMMAND_DITAMAP) {
FakeNode* fn = new DitaMapNode(tre->root(), arg); FakeNode* fn = new DitaMapNode(tree_->root(), arg);
return fn; return fn;
} }
else if (command == COMMAND_QMLCLASS) { else if (command == COMMAND_QMLCLASS) {
const ClassNode* classNode = 0; ClassNode* classNode = 0;
QStringList names = arg.split(QLatin1Char(' ')); QStringList names = arg.split(QLatin1Char(' '));
if (names.size() > 1) { if (names.size() > 1)
Node* n = tre->findNode(names[1].split("::"),Node::Class); classNode = tree_->findClassNode(names[1].split("::"));
if (n) {
classNode = static_cast<const ClassNode*>(n);
}
}
/* /*
Search for a node with the same name. If there is one, Search for a node with the same name. If there is one,
then there is a collision, so create a collision node then there is a collision, so create a collision node
@ -775,15 +775,14 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
If there is no collision, just create a new QML class If there is no collision, just create a new QML class
node and return that one. node and return that one.
*/ */
NameCollisionNode* ncn = tre->checkForCollision(names[0]); NameCollisionNode* ncn = tree_->checkForCollision(names[0]);
QmlClassNode* qcn = new QmlClassNode(tre->root(), names[0], classNode); QmlClassNode* qcn = new QmlClassNode(tree_->root(), names[0], classNode);
if (ncn) { if (ncn)
ncn->addCollision(qcn); ncn->addCollision(qcn);
}
return qcn; return qcn;
} }
else if (command == COMMAND_QMLBASICTYPE) { else if (command == COMMAND_QMLBASICTYPE) {
return new QmlBasicTypeNode(tre->root(), arg); return new QmlBasicTypeNode(tree_->root(), arg);
} }
else if ((command == COMMAND_QMLSIGNAL) || else if ((command == COMMAND_QMLSIGNAL) ||
(command == COMMAND_QMLMETHOD) || (command == COMMAND_QMLMETHOD) ||
@ -793,7 +792,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QString element; QString element;
QString type; QString type;
if (splitQmlMethodArg(doc,arg,type,module,element)) { if (splitQmlMethodArg(doc,arg,type,module,element)) {
QmlClassNode* qmlClass = tre->findQmlClassNode(module,element); QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element);
if (qmlClass) { if (qmlClass) {
if (command == COMMAND_QMLSIGNAL) if (command == COMMAND_QMLSIGNAL)
return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL); return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL);
@ -936,18 +935,18 @@ Node *CppCodeParser::processTopicCommandGroup(const Doc& doc,
bool attached = (command == COMMAND_QMLATTACHEDPROPERTY); bool attached = (command == COMMAND_QMLATTACHEDPROPERTY);
QStringList::ConstIterator arg = args.begin(); QStringList::ConstIterator arg = args.begin();
if (splitQmlPropertyArg(doc,(*arg),type,module,element,property)) { if (splitQmlPropertyArg(doc,(*arg),type,module,element,property)) {
QmlClassNode* qmlClass = tre->findQmlClassNode(module,element); QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element);
if (qmlClass) { if (qmlClass) {
qmlPropGroup = new QmlPropGroupNode(qmlClass,property,attached); qmlPropGroup = new QmlPropGroupNode(qmlClass,property,attached);
} }
} }
if (qmlPropGroup) { if (qmlPropGroup) {
const ClassNode *correspondingClass = static_cast<const QmlClassNode*>(qmlPropGroup->parent())->classNode(); ClassNode *correspondingClass = static_cast<QmlClassNode*>(qmlPropGroup->parent())->classNode();
QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached); QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached);
const PropertyNode *correspondingProperty = 0; const PropertyNode *correspondingProperty = 0;
if (correspondingClass) { if (correspondingClass) {
correspondingProperty = qmlPropNode->correspondingProperty(tre); correspondingProperty = qmlPropNode->correspondingProperty(tree_);
} }
if (correspondingProperty) { if (correspondingProperty) {
bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*'); bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
@ -1053,28 +1052,37 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
} }
} }
else if (command == COMMAND_RELATES) { else if (command == COMMAND_RELATES) {
InnerNode *pseudoParent; /*
Find the node that this node relates to.
*/
Node* n = 0;
if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) { if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) {
pseudoParent = /*
static_cast<InnerNode *>(tre->findNode(QStringList(arg), It should be a header file, I think.
Node::Fake)); */
n = tree_->findNodeByNameAndType(QStringList(arg), Node::Fake, Node::NoSubType, 0);
} }
else { else {
/*
If it wasn't a file, it should be either a class or a namespace.
*/
QStringList newPath = arg.split("::"); QStringList newPath = arg.split("::");
pseudoParent = n = tree_->findClassNode(QStringList(newPath));
static_cast<InnerNode*>(tre->findNode(QStringList(newPath), if (!n)
Node::Class)); n = tree_->findNamespaceNode(QStringList(newPath));
if (!pseudoParent)
pseudoParent =
static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
Node::Namespace));
} }
if (!pseudoParent) {
doc.location().warning(tr("Cannot find '%1' in '\\%2'") if (!n) {
.arg(arg).arg(COMMAND_RELATES)); /*
Didn't ind it. Error...
*/
doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
} }
else { else {
node->setRelates(pseudoParent); /*
Found it. This node relates to it.
*/
node->setRelates(static_cast<InnerNode*>(n));
} }
} }
else if (command == COMMAND_CONTENTSPAGE) { else if (command == COMMAND_CONTENTSPAGE) {
@ -1136,7 +1144,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
} }
} }
else { else {
processCommonMetaCommand(doc.location(),command,arg,node,tre); processCommonMetaCommand(doc.location(),command,arg,node,tree_);
} }
} }
@ -1165,7 +1173,7 @@ void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node)
*/ */
void CppCodeParser::reset(Tree *tree) void CppCodeParser::reset(Tree *tree)
{ {
tre = tree; tree_ = tree;
tokenizer = 0; tokenizer = 0;
tok = 0; tok = 0;
access = Node::Public; access = Node::Public;
@ -1691,7 +1699,7 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
if (!matchDataType(&baseClass)) if (!matchDataType(&baseClass))
return false; return false;
tre->addBaseClass(classe, tree_->addBaseClass(classe,
access, access,
baseClass.toPath(), baseClass.toPath(),
baseClass.toString(), baseClass.toString(),
@ -1773,18 +1781,18 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
So far, so good. We have 'namespace Foo {'. So far, so good. We have 'namespace Foo {'.
*/ */
QString namespaceName = previousLexeme(); QString namespaceName = previousLexeme();
NamespaceNode *namespasse = 0; NamespaceNode* ns = 0;
if (parent) { if (parent) {
namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace)); ns = static_cast<NamespaceNode*>(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace));
} }
if (!namespasse) { if (!ns) {
namespasse = new NamespaceNode(parent, namespaceName); ns = new NamespaceNode(parent, namespaceName);
namespasse->setAccess(access); ns->setAccess(access);
namespasse->setLocation(location()); ns->setLocation(location());
} }
readToken(); // skip '{' readToken(); // skip '{'
bool matched = matchDeclList(namespasse); bool matched = matchDeclList(ns);
return matched && match(Tok_RightBrace); return matched && match(Tok_RightBrace);
} }
@ -1817,7 +1825,7 @@ bool CppCodeParser::matchUsingDecl()
/* /*
So far, so good. We have 'using namespace Foo;'. So far, so good. We have 'using namespace Foo;'.
*/ */
usedNamespaces.insert(name); activeNamespaces_.insert(name);
return true; return true;
} }
@ -1915,10 +1923,10 @@ bool CppCodeParser::matchTypedefDecl(InnerNode *parent)
if (!match(Tok_Semicolon)) if (!match(Tok_Semicolon))
return false; return false;
if (parent && !parent->findNode(name, Node::Typedef)) { if (parent && !parent->findChildNodeByNameAndType(name, Node::Typedef)) {
TypedefNode *typedeffe = new TypedefNode(parent, name); TypedefNode* td = new TypedefNode(parent, name);
typedeffe->setAccess(access); td->setAccess(access);
typedeffe->setLocation(location()); td->setLocation(location());
} }
return true; return true;
} }
@ -1977,9 +1985,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent)
} }
if (key == "READ") if (key == "READ")
tre->addPropertyFunction(property, value, PropertyNode::Getter); tree_->addPropertyFunction(property, value, PropertyNode::Getter);
else if (key == "WRITE") { else if (key == "WRITE") {
tre->addPropertyFunction(property, value, PropertyNode::Setter); tree_->addPropertyFunction(property, value, PropertyNode::Setter);
property->setWritable(true); property->setWritable(true);
} }
else if (key == "STORED") else if (key == "STORED")
@ -1996,9 +2004,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent)
} }
} }
else if (key == "RESET") else if (key == "RESET")
tre->addPropertyFunction(property, value, PropertyNode::Resetter); tree_->addPropertyFunction(property, value, PropertyNode::Resetter);
else if (key == "NOTIFY") { else if (key == "NOTIFY") {
tre->addPropertyFunction(property, value, PropertyNode::Notifier); tree_->addPropertyFunction(property, value, PropertyNode::Notifier);
} else if (key == "REVISION") { } else if (key == "REVISION") {
int revision; int revision;
bool ok; bool ok;
@ -2130,15 +2138,13 @@ bool CppCodeParser::matchDeclList(InnerNode *parent)
if (match(Tok_LeftParen) && match(Tok_Ident)) { if (match(Tok_LeftParen) && match(Tok_Ident)) {
QString flagsType = previousLexeme(); QString flagsType = previousLexeme();
if (match(Tok_Comma) && match(Tok_Ident)) { if (match(Tok_Comma) && match(Tok_Ident)) {
QString enumType = previousLexeme(); QString name = previousLexeme();
TypedefNode *flagsNode = new TypedefNode(parent, flagsType); TypedefNode *flagsNode = new TypedefNode(parent, flagsType);
flagsNode->setAccess(access); flagsNode->setAccess(access);
flagsNode->setLocation(location()); flagsNode->setLocation(location());
EnumNode *enumNode = EnumNode* en = static_cast<EnumNode*>(parent->findChildNodeByNameAndType(name, Node::Enum));
static_cast<EnumNode*>(parent->findNode(enumType, if (en)
Node::Enum)); en->setFlagsType(flagsNode);
if (enumNode)
enumNode->setFlagsType(flagsNode);
} }
} }
match(Tok_RightParen); match(Tok_RightParen);
@ -2219,14 +2225,14 @@ bool CppCodeParser::matchDocsAndStuff()
FunctionNode *func = 0; FunctionNode *func = 0;
if (matchFunctionDecl(0, &parentPath, &clone)) { if (matchFunctionDecl(0, &parentPath, &clone)) {
foreach (const QString &usedNamespace, usedNamespaces) { foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace.split("::") + parentPath; QStringList newPath = usedNamespace_.split("::") + parentPath;
func = tre->findFunctionNode(newPath, clone); func = tree_->findFunctionNode(newPath, clone);
if (func) if (func)
break; break;
} }
if (func == 0) if (func == 0)
func = tre->findFunctionNode(parentPath, clone); func = tree_->findFunctionNode(parentPath, clone);
if (func) { if (func) {
func->borrowParameterNames(clone); func->borrowParameterNames(clone);
@ -2280,7 +2286,7 @@ bool CppCodeParser::matchDocsAndStuff()
if ((*n)->isInnerNode() && if ((*n)->isInnerNode() &&
((InnerNode *)*n)->includes().isEmpty()) { ((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n); InnerNode *m = static_cast<InnerNode *>(*n);
while (m->parent() != tre->root()) while (m->parent() != tree_->root())
m = m->parent(); m = m->parent();
if (m == *n) if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name()); ((InnerNode *)*n)->addInclude((*n)->name());
@ -2309,7 +2315,7 @@ bool CppCodeParser::matchDocsAndStuff()
Signals are implemented in uninteresting files Signals are implemented in uninteresting files
generated by moc. generated by moc.
*/ */
node = tre->findFunctionNode(parentPath, clone); node = tree_->findFunctionNode(parentPath, clone);
if (node != 0 && node->metaness() != FunctionNode::Signal) if (node != 0 && node->metaness() != FunctionNode::Signal)
node->setLocation(clone->location()); node->setLocation(clone->location());
delete clone; delete clone;
@ -2421,7 +2427,7 @@ void CppCodeParser::instantiateIteratorMacro(const QString &container,
Tokenizer stringTokenizer(loc, latin1); Tokenizer stringTokenizer(loc, latin1);
tokenizer = &stringTokenizer; tokenizer = &stringTokenizer;
readToken(); readToken();
matchDeclList(tre->root()); matchDeclList(tree_->root());
} }
void CppCodeParser::createExampleFileNodes(FakeNode *fake) void CppCodeParser::createExampleFileNodes(FakeNode *fake)

View File

@ -165,7 +165,7 @@ private:
void createExampleFileNodes(FakeNode *fake); void createExampleFileNodes(FakeNode *fake);
QMap<QString, Node::Type> nodeTypeMap; QMap<QString, Node::Type> nodeTypeMap;
Tree *tre; Tree* tree_;
Tokenizer *tokenizer; Tokenizer *tokenizer;
int tok; int tok;
Node::Access access; Node::Access access;
@ -179,7 +179,7 @@ private:
QString mutableSequentialIteratorDefinition; QString mutableSequentialIteratorDefinition;
QString associativeIteratorDefinition; QString associativeIteratorDefinition;
QString mutableAssociativeIteratorDefinition; QString mutableAssociativeIteratorDefinition;
QSet<QString> usedNamespaces; QSet<QString> activeNamespaces_;
QMap<QString, QString> sequentialIteratorClasses; QMap<QString, QString> sequentialIteratorClasses;
QMap<QString, QString> mutableSequentialIteratorClasses; QMap<QString, QString> mutableSequentialIteratorClasses;
QMap<QString, QString> associativeIteratorClasses; QMap<QString, QString> associativeIteratorClasses;

View File

@ -418,7 +418,6 @@ DitaXmlGenerator::DitaXmlGenerator()
sectionNestingLevel(0), sectionNestingLevel(0),
tableColumnCount(0), tableColumnCount(0),
funcLeftParen("\\S(\\()"), funcLeftParen("\\S(\\()"),
tree_(0),
nodeTypeMaps(Node::LastType,0), nodeTypeMaps(Node::LastType,0),
nodeSubtypeMaps(Node::LastSubtype,0), nodeSubtypeMaps(Node::LastSubtype,0),
pageTypeMaps(Node::OnBeyondZebra,0) pageTypeMaps(Node::OnBeyondZebra,0)
@ -618,7 +617,7 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
This is where the DITA XML files are written. This is where the DITA XML files are written.
\note The file is created in PageGenerator::generateTree(). \note The file is created in PageGenerator::generateTree().
*/ */
void DitaXmlGenerator::generateTree(const Tree *tree) void DitaXmlGenerator::generateTree(Tree *tree)
{ {
tree_ = tree; tree_ = tree;
nonCompatClasses.clear(); nonCompatClasses.clear();
@ -638,6 +637,7 @@ void DitaXmlGenerator::generateTree(const Tree *tree)
findAllSince(tree->root()); findAllSince(tree->root());
Generator::generateTree(tree); Generator::generateTree(tree);
generateCollisionPages();
writeDitaMap(tree); writeDitaMap(tree);
} }
@ -1269,19 +1269,15 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
const Node *node = 0; const Node *node = 0;
QString myLink = getLink(atom, relative, marker, &node); QString myLink = getLink(atom, relative, marker, &node);
if (myLink.isEmpty()) { if (myLink.isEmpty()) {
relative->doc().location().warning(tr("Can't link to '%1' in %2") myLink = getCollisionLink(atom);
.arg(atom->string()) }
.arg(marker->plainFullName(relative))); if (myLink.isEmpty()) {
relative->doc().location().warning(tr("Can't link to '%1'")
.arg(atom->string()));
} }
else if (!inSectionHeading) { else if (!inSectionHeading) {
beginLink(myLink); beginLink(myLink);
} }
#if 0
else {
//xmlWriter().writeCharacters(atom->string());
//qDebug() << "MYLINK:" << myLink << outFileName() << atom->string();
}
#endif
skipAhead = 1; skipAhead = 1;
} }
break; break;
@ -1744,7 +1740,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
for marking up the code. I don't know what that means exactly. for marking up the code. I don't know what that means exactly.
*/ */
void void
DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker) DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
{ {
QList<Section>::ConstIterator s; QList<Section>::ConstIterator s;
@ -2143,8 +2139,8 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
writeEndTag(); // </cxxClass> writeEndTag(); // </cxxClass>
} }
else if ((inner->type() == Node::Fake) && (inner->subType() == Node::QmlClass)) { else if ((inner->type() == Node::Fake) && (inner->subType() == Node::QmlClass)) {
const QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner)); QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner));
const ClassNode* cn = qcn->classNode(); ClassNode* cn = qcn->classNode();
rawTitle = marker->plainName(inner); rawTitle = marker->plainName(inner);
fullTitle = marker->plainFullName(inner); fullTitle = marker->plainFullName(inner);
title = rawTitle + " Element"; title = rawTitle + " Element";
@ -2248,7 +2244,7 @@ void DitaXmlGenerator::writeXrefListItem(const QString& link, const QString& tex
Generate the DITA page for a qdoc file that doesn't map Generate the DITA page for a qdoc file that doesn't map
to an underlying c++ file. to an underlying c++ file.
*/ */
void DitaXmlGenerator::generateFakeNode(const FakeNode* fake, CodeMarker* marker) void DitaXmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker)
{ {
/* /*
If the fake node is a page node, and if the page type If the fake node is a page node, and if the page type
@ -2499,6 +2495,9 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::ExternalPage: // not used case Node::ExternalPage: // not used
outputclass = "externalpage"; outputclass = "externalpage";
break; break;
case Node::Collision:
outputclass = "collision";
break;
default: default:
outputclass = "page"; outputclass = "page";
} }
@ -3302,16 +3301,11 @@ void DitaXmlGenerator::generateOverviewList(const Node* relative, CodeMarker* /*
else if (!isGroupPage) { else if (!isGroupPage) {
// If we encounter a page that belongs to a group then // If we encounter a page that belongs to a group then
// we add that page to the list for that group. // we add that page to the list for that group.
const FakeNode* groupNode = const FakeNode* gn = tree_->findGroupNode(QStringList(group));
static_cast<const FakeNode*>(tree_->root()->findNode(group, Node::Fake)); if (gn)
if (groupNode) fakeNodeMap[gn].insert(sortKey, fakeNode);
fakeNodeMap[groupNode].insert(sortKey, fakeNode); }
//else }
// uncategorizedNodeMap.insert(sortKey, fakeNode);
}// else
// uncategorizedNodeMap.insert(sortKey, fakeNode);
}// else
// uncategorizedNodeMap.insert(sortKey, fakeNode);
} }
} }
@ -3877,8 +3871,6 @@ QString DitaXmlGenerator::guidForNode(const Node* node)
return node->guid(); return node->guid();
case Node::Variable: case Node::Variable:
return node->guid(); return node->guid();
case Node::Target:
return node->guid();
} }
return QString(); return QString();
} }
@ -4143,7 +4135,7 @@ const Node* DitaXmlGenerator::findNodeForTarget(const QString& target,
node = relative; node = relative;
} }
else if (target.endsWith(".html")) { else if (target.endsWith(".html")) {
node = tree_->root()->findNode(target, Node::Fake); node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake);
} }
else if (marker) { else if (marker) {
node = marker->resolveTarget(target, tree_, relative); node = marker->resolveTarget(target, tree_, relative);
@ -4204,7 +4196,7 @@ QString DitaXmlGenerator::getLink(const Atom* atom,
*node = relative; *node = relative;
} }
else if (first.endsWith(".html")) { else if (first.endsWith(".html")) {
*node = tree_->root()->findNode(first, Node::Fake); *node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake);
} }
else { else {
*node = marker->resolveTarget(first, tree_, relative); *node = marker->resolveTarget(first, tree_, relative);
@ -4292,17 +4284,6 @@ QString DitaXmlGenerator::getLink(const Atom* atom,
return link; return link;
} }
/*!
This function can be called if getLink() returns an empty
string.
*/
QString DitaXmlGenerator::getDisambiguationLink(const Atom *, CodeMarker *)
{
qDebug() << "Unimplemented function called: "
<< "QString DitaXmlGenerator::getDisambiguationLink()";
return QString();
}
void DitaXmlGenerator::generateIndex(const QString& fileBase, void DitaXmlGenerator::generateIndex(const QString& fileBase,
const QString& url, const QString& url,
const QString& title) const QString& title)
@ -4419,19 +4400,19 @@ void DitaXmlGenerator::generateQmlSummary(const Section& section,
Outputs the DITA detailed documentation for a section Outputs the DITA detailed documentation for a section
on a QML element reference page. on a QML element reference page.
*/ */
void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, void DitaXmlGenerator::generateDetailedQmlMember(Node* node,
const InnerNode* relative, const InnerNode* relative,
CodeMarker* marker) CodeMarker* marker)
{ {
QString marked; QString marked;
const QmlPropertyNode* qpn = 0; QmlPropertyNode* qpn = 0;
if (node->subType() == Node::QmlPropertyGroup) { if (node->subType() == Node::QmlPropertyGroup) {
const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().begin(); NodeList::ConstIterator p = qpgn->childNodes().begin();
writeStartTag(DT_ul); writeStartTag(DT_ul);
while (p != qpgn->childNodes().end()) { while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) { if ((*p)->type() == Node::QmlProperty) {
qpn = static_cast<const QmlPropertyNode*>(*p); qpn = static_cast<QmlPropertyNode*>(*p);
writeStartTag(DT_li); writeStartTag(DT_li);
writeGuidAttribute((Node*)qpn); writeGuidAttribute((Node*)qpn);
QString attr; QString attr;
@ -4457,7 +4438,7 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node* node,
writeEndTag(); // </ul> writeEndTag(); // </ul>
} }
else if (node->type() == Node::QmlProperty) { else if (node->type() == Node::QmlProperty) {
qpn = static_cast<const QmlPropertyNode*>(node); qpn = static_cast<QmlPropertyNode*>(node);
/* /*
If the QML property node has a single subproperty, If the QML property node has a single subproperty,
override, replace qpn with that override node and override, replace qpn with that override node and
@ -4466,7 +4447,7 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node* node,
if (qpn->qmlPropNodes().size() == 1) { if (qpn->qmlPropNodes().size() == 1) {
Node* n = qpn->qmlPropNodes().at(0); Node* n = qpn->qmlPropNodes().at(0);
if (n->type() == Node::QmlProperty) if (n->type() == Node::QmlProperty)
qpn = static_cast<const QmlPropertyNode*>(n); qpn = static_cast<QmlPropertyNode*>(n);
} }
/* /*
Now qpn either has no overrides, or it has more Now qpn either has no overrides, or it has more
@ -4600,10 +4581,9 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker*
If there is no class node, or if the class node status If there is no class node, or if the class node status
is set to Node::Internal, do nothing. is set to Node::Internal, do nothing.
*/ */
void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, void DitaXmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker)
CodeMarker* marker)
{ {
const ClassNode* cn = qcn->classNode(); ClassNode* cn = qcn->classNode();
if (cn && (cn->status() != Node::Internal)) { if (cn && (cn->status() != Node::Internal)) {
writeStartTag(DT_p); writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","instantiates"); xmlWriter().writeAttribute("outputclass","instantiates");
@ -4631,8 +4611,7 @@ void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
If there is no QML element, or if the class node status If there is no QML element, or if the class node status
is set to Node::Internal, do nothing. is set to Node::Internal, do nothing.
*/ */
void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn, void DitaXmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker)
CodeMarker* marker)
{ {
if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) { if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) {
const QmlClassNode* qcn = cn->qmlElement(); const QmlClassNode* qcn = cn->qmlElement();
@ -5628,13 +5607,13 @@ void DitaXmlGenerator::writeNestedClasses(const Section& s,
Recursive writing of DITA XML files from the root \a node. Recursive writing of DITA XML files from the root \a node.
*/ */
void void
DitaXmlGenerator::generateInnerNode(const InnerNode* node) DitaXmlGenerator::generateInnerNode(InnerNode* node)
{ {
if (!node->url().isNull()) if (!node->url().isNull())
return; return;
if (node->type() == Node::Fake) { if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode *>(node); FakeNode* fakeNode = static_cast<FakeNode*>(node);
if (fakeNode->subType() == Node::ExternalPage) if (fakeNode->subType() == Node::ExternalPage)
return; return;
if (fakeNode->subType() == Node::Image) if (fakeNode->subType() == Node::Image)
@ -5653,27 +5632,38 @@ DitaXmlGenerator::generateInnerNode(const InnerNode* node)
CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath()); CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
if (node->parent() != 0) { if (node->parent() != 0) {
if (!node->name().endsWith(".ditamap")) /*
beginSubPage(node, fileName(node)); Skip name collision nodes here and process them
if (node->type() == Node::Namespace || node->type() == Node::Class) { later in generateCollisionPages(). Each one is
generateClassLikeNode(node, marker); appended to a list for later.
*/
if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
} }
else if (node->type() == Node::Fake) { else {
if (node->subType() == Node::HeaderFile) if (!node->name().endsWith(".ditamap"))
beginSubPage(node, fileName(node));
if (node->type() == Node::Namespace || node->type() == Node::Class) {
generateClassLikeNode(node, marker); generateClassLikeNode(node, marker);
else if (node->subType() == Node::QmlClass) }
generateClassLikeNode(node, marker); else if (node->type() == Node::Fake) {
else if (node->subType() == Node::HeaderFile)
generateFakeNode(static_cast<const FakeNode*>(node), marker); generateClassLikeNode(node, marker);
else if (node->subType() == Node::QmlClass)
generateClassLikeNode(node, marker);
else
generateFakeNode(static_cast<FakeNode*>(node), marker);
}
if (!node->name().endsWith(".ditamap"))
endSubPage();
} }
if (!node->name().endsWith(".ditamap"))
endSubPage();
} }
NodeList::ConstIterator c = node->childNodes().begin(); NodeList::ConstIterator c = node->childNodes().begin();
while (c != node->childNodes().end()) { while (c != node->childNodes().end()) {
if ((*c)->isInnerNode() && (*c)->access() != Node::Private) if ((*c)->isInnerNode() && (*c)->access() != Node::Private)
generateInnerNode((const InnerNode*) *c); generateInnerNode((InnerNode*)*c);
++c; ++c;
} }
} }
@ -5819,8 +5809,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
break; break;
case Node::Variable: case Node::Variable:
break; break;
case Node::Target:
break;
case Node::QmlProperty: case Node::QmlProperty:
break; break;
case Node::QmlSignal: case Node::QmlSignal:
@ -5840,7 +5828,7 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
Creates the DITA map for the qdoc run. The map is written Creates the DITA map for the qdoc run. The map is written
to the file \e{qt.ditamap" in the DITA XML output directory. to the file \e{qt.ditamap" in the DITA XML output directory.
*/ */
void DitaXmlGenerator::writeDitaMap(const Tree *tree) void DitaXmlGenerator::writeDitaMap(Tree *tree)
{ {
QString doctype; QString doctype;
@ -6374,5 +6362,125 @@ QString DitaXmlGenerator::stripMarkup(const QString& src) const
return text; return text;
} }
/*!
We delayed generation of the collision pages until now, after
all the other pages have been generated. We do this because we might
encounter a link command that tries to link to a target on a QML
type page, but the link doesn't specify the module identifer
for the QML type, and the QML type name without a module
identifier is ambiguous. When such a link is found, qdoc can't find
the target, so it appends the target to the NameCollisionNode. After
the tree has been traversed and all these ambiguous links have been
added to the name collision nodes, this function is called. The list
of collision nodes is traversed here, and the collision page for
each collision is generated. The collision page will not only
disambiguate links to the QML type pages, but it will also disambiguate
links to properties, section headers, etc.
*/
void DitaXmlGenerator::generateCollisionPages()
{
if (collisionNodes.isEmpty())
return;
for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
if (!ncn)
continue;
NodeList collisions;
const NodeList& nl = ncn->childNodes();
if (!nl.isEmpty()) {
NodeList::ConstIterator it = nl.begin();
while (it != nl.end()) {
if (!(*it)->isInternal())
collisions.append(*it);
++it;
}
}
if (collisions.size() <= 1)
continue;
ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->fullTitle();
QString ditaTitle = fullTitle;
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
if (ncn->isQmlNode()) {
// Replace the marker with a QML code marker.
if (ncn->isQmlNode())
marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
}
generateHeader(ncn, ditaTitle);
writeProlog(ncn);
writeStartTag(DT_body);
enterSection(QString(),QString());
NodeMap nm;
for (int i=0; i<collisions.size(); ++i) {
Node* n = collisions.at(i);
QString t;
if (!n->qmlModuleIdentifier().isEmpty())
t = n->qmlModuleIdentifier() + " ";
t += protectEnc(fullTitle);
nm.insertMulti(t,n);
}
generateAnnotatedList(ncn, marker, nm);
QList<QString> targets;
if (!ncn->linkTargets().isEmpty()) {
QMap<QString,QString>::ConstIterator t = ncn->linkTargets().begin();
while (t != ncn->linkTargets().end()) {
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
if (n->findChildNodeByName(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
break;
}
}
}
++t;
}
}
if (!targets.isEmpty()) {
QList<QString>::ConstIterator t = targets.begin();
while (t != targets.end()) {
writeStartTag(DT_p);
writeGuidAttribute(Doc::canonicalTitle(*t));
xmlWriter().writeAttribute("outputclass","h2");
writeCharacters(protectEnc(*t));
writeEndTag(); // </p>
writeStartTag(DT_ul);
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
Node* p = n->findChildNodeByName(*t);
if (p) {
QString link = linkForNode(p,0);
QString label;
if (!n->qmlModuleIdentifier().isEmpty())
label = n->qmlModuleIdentifier() + "::";
label += n->name() + "::" + p->name();
writeStartTag(DT_li);
writeStartTag(DT_xref);
xmlWriter().writeAttribute("href", link);
writeCharacters(protectEnc(label));
writeEndTag(); // </xref>
writeEndTag(); // </li>
}
}
writeEndTag(); // </ul>
++t;
}
}
leaveSection(); // </section>
writeEndTag(); // </body>
endSubPage();
}
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -266,8 +266,8 @@ public:
virtual void terminateGenerator(); virtual void terminateGenerator();
virtual QString format(); virtual QString format();
virtual bool canHandleFormat(const QString& format); virtual bool canHandleFormat(const QString& format);
virtual void generateTree(const Tree *tree); virtual void generateTree(Tree *tree);
virtual void generateDisambiguationPages() { } void generateCollisionPages();
QString protectEnc(const QString& string); QString protectEnc(const QString& string);
static QString protect(const QString& string, const QString& encoding = "ISO-8859-1"); static QString protect(const QString& string, const QString& encoding = "ISO-8859-1");
@ -279,8 +279,8 @@ protected:
virtual int generateAtom(const Atom* atom, virtual int generateAtom(const Atom* atom,
const Node* relative, const Node* relative,
CodeMarker* marker); CodeMarker* marker);
virtual void generateClassLikeNode(const InnerNode* inner, CodeMarker* marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateFakeNode(const FakeNode* fake, CodeMarker* marker); virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual QString fileExtension(const Node* node) const; virtual QString fileExtension(const Node* node) const;
virtual QString guidForNode(const Node* node); virtual QString guidForNode(const Node* node);
virtual QString linkForNode(const Node* node, const Node* relative); virtual QString linkForNode(const Node* node, const Node* relative);
@ -377,12 +377,12 @@ private:
const Node* relative, const Node* relative,
CodeMarker* marker, CodeMarker* marker,
bool summary); bool summary);
void generateDetailedQmlMember(const Node* node, void generateDetailedQmlMember(Node* node,
const InnerNode* relative, const InnerNode* relative,
CodeMarker* marker); CodeMarker* marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
void generateSection(const NodeList& nl, void generateSection(const NodeList& nl,
const Node* relative, const Node* relative,
@ -421,7 +421,6 @@ private:
const Node *relative, const Node *relative,
CodeMarker *marker, CodeMarker *marker,
const Node **node); const Node **node);
QString getDisambiguationLink(const Atom* atom, CodeMarker* marker);
virtual void generateIndex(const QString& fileBase, virtual void generateIndex(const QString& fileBase,
const QString& url, const QString& url,
const QString& title); const QString& title);
@ -437,11 +436,11 @@ private:
GuidMap* lookupGuidMap(const QString& fileName); GuidMap* lookupGuidMap(const QString& fileName);
virtual void beginSubPage(const InnerNode* node, const QString& fileName); virtual void beginSubPage(const InnerNode* node, const QString& fileName);
virtual void endSubPage(); virtual void endSubPage();
virtual void generateInnerNode(const InnerNode* node); virtual void generateInnerNode(InnerNode* node);
QXmlStreamWriter& xmlWriter(); QXmlStreamWriter& xmlWriter();
void writeApiDesc(const Node* node, CodeMarker* marker, const QString& title); void writeApiDesc(const Node* node, CodeMarker* marker, const QString& title);
void addLink(const QString& href, const QStringRef& text, DitaTag t = DT_xref); void addLink(const QString& href, const QStringRef& text, DitaTag t = DT_xref);
void writeDitaMap(const Tree* tree); void writeDitaMap(Tree* tree);
void writeDitaMap(const DitaMapNode* node); void writeDitaMap(const DitaMapNode* node);
void writeStartTag(DitaTag t); void writeStartTag(DitaTag t);
bool writeEndTag(DitaTag t=DT_NONE); bool writeEndTag(DitaTag t=DT_NONE);
@ -501,7 +500,6 @@ private:
QStringList vrm; QStringList vrm;
QStringList stylesheets; QStringList stylesheets;
QStringList customHeadElements; QStringList customHeadElements;
const Tree* tree_;
QMap<QString, QString> refMap; QMap<QString, QString> refMap;
QMap<QString, QString> name2guidMap; QMap<QString, QString> name2guidMap;
GuidMaps guidMaps; GuidMaps guidMaps;

View File

@ -102,7 +102,8 @@ Generator::Generator()
gt("&gt;"), gt("&gt;"),
lt("&lt;"), lt("&lt;"),
quot("&quot;"), quot("&quot;"),
tag("</?@[^>]*>") tag("</?@[^>]*>"),
tree_(0)
{ {
generators.prepend(this); generators.prepend(this);
} }
@ -452,11 +453,12 @@ QString Generator::fullName(const Node *node,
{ {
if (node->type() == Node::Fake) { if (node->type() == Node::Fake) {
const FakeNode* fn = static_cast<const FakeNode *>(node); const FakeNode* fn = static_cast<const FakeNode *>(node);
#if 0
// Removed for QTBUG-22870 // Removed for QTBUG-22870
// Unremoved by mws 30/03/12
if (!fn->qmlModuleIdentifier().isEmpty()) if (!fn->qmlModuleIdentifier().isEmpty())
return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title(); return fn->qmlModuleIdentifier() + "::" + fn->title();
#endif
return fn->title(); return fn->title();
} }
else if (node->type() == Node::Class && else if (node->type() == Node::Class &&
@ -700,8 +702,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
} }
} }
void Generator::generateClassLikeNode(const InnerNode * /* classe */, void Generator::generateClassLikeNode(InnerNode* /* classe */, CodeMarker* /* marker */)
CodeMarker * /* marker */)
{ {
} }
@ -713,8 +714,7 @@ void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
generateFileList(fake, marker, Node::Image, QString("Images:")); generateFileList(fake, marker, Node::Image, QString("Images:"));
} }
void Generator::generateFakeNode(const FakeNode * /* fake */, void Generator::generateFakeNode(FakeNode* /* fake */, CodeMarker* /* marker */)
CodeMarker * /* marker */)
{ {
} }
@ -837,16 +837,16 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
Recursive writing of HTML files from the root \a node. Recursive writing of HTML files from the root \a node.
\note NameCollisionNodes are skipped here and processed \note NameCollisionNodes are skipped here and processed
later. See HtmlGenerator::generateDisambiguationPages() later. See HtmlGenerator::generateCollisionPages() for
for more on this. more on this.
*/ */
void Generator::generateInnerNode(const InnerNode* node) void Generator::generateInnerNode(InnerNode* node)
{ {
if (!node->url().isNull()) if (!node->url().isNull())
return; return;
if (node->type() == Node::Fake) { if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode *>(node); FakeNode* fakeNode = static_cast<FakeNode*>(node);
if (fakeNode->subType() == Node::ExternalPage) if (fakeNode->subType() == Node::ExternalPage)
return; return;
if (fakeNode->subType() == Node::Image) if (fakeNode->subType() == Node::Image)
@ -867,11 +867,11 @@ void Generator::generateInnerNode(const InnerNode* node)
if (node->parent() != 0) { if (node->parent() != 0) {
/* /*
Skip name collision nodes here and process them Skip name collision nodes here and process them
later in generateDisambiguationPages(). Each one later in generateCollisionPages(). Each one is
is appended to a list for later. appended to a list for later.
*/ */
if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) { if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node); NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn)); collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
} }
else { else {
@ -880,7 +880,7 @@ void Generator::generateInnerNode(const InnerNode* node)
generateClassLikeNode(node, marker); generateClassLikeNode(node, marker);
} }
else if (node->type() == Node::Fake) { else if (node->type() == Node::Fake) {
generateFakeNode(static_cast<const FakeNode *>(node), marker); generateFakeNode(static_cast<FakeNode*>(node), marker);
} }
endSubPage(); endSubPage();
} }
@ -889,7 +889,7 @@ void Generator::generateInnerNode(const InnerNode* node)
NodeList::ConstIterator c = node->childNodes().begin(); NodeList::ConstIterator c = node->childNodes().begin();
while (c != node->childNodes().end()) { while (c != node->childNodes().end()) {
if ((*c)->isInnerNode() && (*c)->access() != Node::Private) { if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
generateInnerNode((const InnerNode *) *c); generateInnerNode((InnerNode*)*c);
} }
++c; ++c;
} }
@ -1249,8 +1249,9 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
/*! /*!
This function is recursive. This function is recursive.
*/ */
void Generator::generateTree(const Tree *tree) void Generator::generateTree(Tree *tree)
{ {
tree_ = tree;
generateInnerNode(tree->root()); generateInnerNode(tree->root());
} }
@ -1265,6 +1266,40 @@ Generator *Generator::generatorForFormat(const QString& format)
return 0; return 0;
} }
/*!
This function can be called if getLink() returns an empty
string. It tests the \a atom string to see if it is a link
of the form <element> :: <name>, where <element> is a QML
element or component without a module qualifier. If so, it
constructs a link to the <name> clause on the disambiguation
page for <element> and returns that link string. It also
adds the <name> as a target in the NameCollisionNode for
<element>. These clauses are then constructed when the
disambiguation page is actually generated.
*/
QString Generator::getCollisionLink(const Atom* atom)
{
QString link;
if (!atom->string().contains("::"))
return link;
QStringList path = atom->string().split("::");
NameCollisionNode* ncn = tree_->findCollisionNode(path[0]);
if (ncn) {
QString label;
if (atom->next() && atom->next()->next()) {
if (atom->next()->type() == Atom::FormattingLeft &&
atom->next()->next()->type() == Atom::String)
label = atom->next()->next()->string();
}
ncn->addLinkTarget(path[1],label);
link = fileName(ncn);
link += QLatin1Char('#');
link += Doc::canonicalTitle(path[1]);
}
return link;
}
/*! /*!
Looks up the tag \a t in the map of metadata values for the Looks up the tag \a t in the map of metadata values for the
current topic in \a inner. If a value for the tag is found, current topic in \a inner. If a value for the tag is found,

View File

@ -85,7 +85,7 @@ public:
virtual bool canHandleFormat(const QString &format) { return format == this->format(); } virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
virtual QString format() = 0; virtual QString format() = 0;
virtual void generateTree(const Tree *tree); virtual void generateTree(Tree *tree);
virtual void initializeGenerator(const Config &config); virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator(); virtual void terminateGenerator();
@ -109,13 +109,13 @@ protected:
const Node *relative, const Node *relative,
CodeMarker *marker); CodeMarker *marker);
virtual void generateBody(const Node *node, CodeMarker *marker); virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual void generateInheritedBy(const ClassNode *classe, virtual void generateInheritedBy(const ClassNode *classe,
CodeMarker *marker); CodeMarker *marker);
virtual void generateInherits(const ClassNode *classe, virtual void generateInherits(const ClassNode *classe,
CodeMarker *marker); CodeMarker *marker);
virtual void generateInnerNode(const InnerNode *node); virtual void generateInnerNode(InnerNode* node);
virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker); virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker); virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
@ -155,6 +155,7 @@ protected:
void generateSince(const Node *node, CodeMarker *marker); void generateSince(const Node *node, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker);
void generateThreadSafeness(const Node *node, CodeMarker *marker); void generateThreadSafeness(const Node *node, CodeMarker *marker);
QString getCollisionLink(const Atom* atom);
QString getMetadataElement(const InnerNode* inner, const QString& t); QString getMetadataElement(const InnerNode* inner, const QString& t);
QStringList getMetadataElements(const InnerNode* inner, const QString& t); QStringList getMetadataElements(const InnerNode* inner, const QString& t);
QString indent(int level, const QString& markedCode); QString indent(int level, const QString& markedCode);
@ -230,6 +231,9 @@ private:
QString lt; QString lt;
QString quot; QString quot;
QRegExp tag; QRegExp tag;
protected:
Tree* tree_;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -117,13 +117,10 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["function"] = Node::Function; typeHash["function"] = Node::Function;
typeHash["property"] = Node::Property; typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable; typeHash["variable"] = Node::Variable;
typeHash["target"] = Node::Target;
#ifdef QDOC_QML
typeHash["qmlproperty"] = Node::QmlProperty; typeHash["qmlproperty"] = Node::QmlProperty;
typeHash["qmlsignal"] = Node::QmlSignal; typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler; typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
typeHash["qmlmethod"] = Node::QmlMethod; typeHash["qmlmethod"] = Node::QmlMethod;
#endif
QHash<QString, Node::SubType> subTypeHash; QHash<QString, Node::SubType> subTypeHash;
subTypeHash["example"] = Node::Example; subTypeHash["example"] = Node::Example;
@ -133,11 +130,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["module"] = Node::Module; subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page; subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage; subTypeHash["externalpage"] = Node::ExternalPage;
#ifdef QDOC_QML
subTypeHash["qmlclass"] = Node::QmlClass; subTypeHash["qmlclass"] = Node::QmlClass;
subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup; subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
subTypeHash["qmlbasictype"] = Node::QmlBasicType; subTypeHash["qmlbasictype"] = Node::QmlBasicType;
#endif
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values()); QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());

View File

@ -100,7 +100,6 @@ HtmlGenerator::HtmlGenerator()
numTableRows(0), numTableRows(0),
threeColumnEnumValueTable(true), threeColumnEnumValueTable(true),
funcLeftParen("\\S(\\()"), funcLeftParen("\\S(\\()"),
myTree(0),
obsoleteLinks(false) obsoleteLinks(false)
{ {
} }
@ -255,9 +254,9 @@ QString HtmlGenerator::format()
\note The HTML file generation is done in the base class, \note The HTML file generation is done in the base class,
PageGenerator::generateTree(). PageGenerator::generateTree().
*/ */
void HtmlGenerator::generateTree(const Tree *tree) void HtmlGenerator::generateTree(Tree *tree)
{ {
myTree = tree; tree_ = tree;
nonCompatClasses.clear(); nonCompatClasses.clear();
mainClasses.clear(); mainClasses.clear();
compatClasses.clear(); compatClasses.clear();
@ -268,6 +267,7 @@ void HtmlGenerator::generateTree(const Tree *tree)
legaleseTexts.clear(); legaleseTexts.clear();
serviceClasses.clear(); serviceClasses.clear();
qmlClasses.clear(); qmlClasses.clear();
findAllClasses(tree->root()); findAllClasses(tree->root());
findAllFunctions(tree->root()); findAllFunctions(tree->root());
findAllLegaleseTexts(tree->root()); findAllLegaleseTexts(tree->root());
@ -275,13 +275,13 @@ void HtmlGenerator::generateTree(const Tree *tree)
findAllSince(tree->root()); findAllSince(tree->root());
Generator::generateTree(tree); Generator::generateTree(tree);
reportOrphans(tree->root()); //reportOrphans(tree->root());
generateDisambiguationPages(); generateCollisionPages();
QString fileBase = project.toLower().simplified().replace(" ", "-"); QString fileBase = project.toLower().simplified().replace(" ", "-");
generateIndex(fileBase, projectUrl, projectDescription); generateIndex(fileBase, projectUrl, projectDescription);
helpProjectWriter->generate(myTree); helpProjectWriter->generate(tree_);
generateManifestFiles(); generateManifestFiles();
} }
@ -492,7 +492,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
break; break;
case Atom::AnnotatedList: case Atom::AnnotatedList:
{ {
QList<Node*> values = myTree->groups().values(atom->string()); QList<Node*> values = tree_->groups().values(atom->string());
NodeMap nodeMap; NodeMap nodeMap;
for (int i = 0; i < values.size(); ++i) { for (int i = 0; i < values.size(); ++i) {
const Node* n = values.at(i); const Node* n = values.at(i);
@ -538,7 +538,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
// Add additional groups and remove groups of classes that // Add additional groups and remove groups of classes that
// should be excluded from the edition. // should be excluded from the edition.
QMultiMap <QString, Node *> groups = myTree->groups(); QMultiMap <QString, Node *> groups = tree_->groups();
foreach (const QString &groupName, editionGroupMap[editionName]) { foreach (const QString &groupName, editionGroupMap[editionName]) {
QList<Node *> groupClasses; QList<Node *> groupClasses;
if (groupName.startsWith(QLatin1Char('-'))) { if (groupName.startsWith(QLatin1Char('-'))) {
@ -833,7 +833,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
const Node *node = 0; const Node *node = 0;
QString myLink = getLink(atom, relative, marker, &node); QString myLink = getLink(atom, relative, marker, &node);
if (myLink.isEmpty()) { if (myLink.isEmpty()) {
myLink = getDisambiguationLink(atom, marker); myLink = getCollisionLink(atom);
if (myLink.isEmpty()) { if (myLink.isEmpty()) {
relative->doc().location().warning(tr("Can't create link to '%1'") relative->doc().location().warning(tr("Can't create link to '%1'")
.arg(atom->string())); .arg(atom->string()));
@ -1160,13 +1160,12 @@ int HtmlGenerator::generateAtom(const Atom *atom,
/*! /*!
Generate a reference page for a C++ class. Generate a reference page for a C++ class.
*/ */
void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
CodeMarker *marker)
{ {
QList<Section> sections; QList<Section> sections;
QList<Section>::ConstIterator s; QList<Section>::ConstIterator s;
const ClassNode *classe = 0; ClassNode* classe = 0;
QString title; QString title;
QString rawTitle; QString rawTitle;
@ -1177,7 +1176,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
title = rawTitle + " Namespace"; title = rawTitle + " Namespace";
} }
else if (inner->type() == Node::Class) { else if (inner->type() == Node::Class) {
classe = static_cast<const ClassNode *>(inner); classe = static_cast<ClassNode*>(inner);
rawTitle = marker->plainName(inner); rawTitle = marker->plainName(inner);
fullTitle = marker->plainFullName(inner); fullTitle = marker->plainFullName(inner);
title = rawTitle + " Class"; title = rawTitle + " Class";
@ -1370,15 +1369,32 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
disambiguate links to the component pages, but it will also disambiguate disambiguate links to the component pages, but it will also disambiguate
links to properties, section headers, etc. links to properties, section headers, etc.
*/ */
void HtmlGenerator::generateDisambiguationPages() void HtmlGenerator::generateCollisionPages()
{ {
if (collisionNodes.isEmpty()) if (collisionNodes.isEmpty())
return; return;
for (int i=0; i<collisionNodes.size(); ++i) { for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i); NameCollisionNode* ncn = collisionNodes.at(i);
if (!ncn)
continue;
NodeList collisions;
const NodeList& nl = ncn->childNodes();
if (!nl.isEmpty()) {
NodeList::ConstIterator it = nl.begin();
while (it != nl.end()) {
if (!(*it)->isInternal())
collisions.append(*it);
++it;
}
}
if (collisions.size() <= 1)
continue;
ncn->clearCurrentChild(); ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn)); beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = "Name Collision: " + ncn->fullTitle(); QString fullTitle = ncn->fullTitle();
QString htmlTitle = fullTitle; QString htmlTitle = fullTitle;
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath()); CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
if (ncn->isQmlNode()) { if (ncn->isQmlNode()) {
@ -1390,36 +1406,56 @@ void HtmlGenerator::generateDisambiguationPages()
generateHeader(htmlTitle, ncn, marker); generateHeader(htmlTitle, ncn, marker);
if (!fullTitle.isEmpty()) if (!fullTitle.isEmpty())
out() << "<h1 class=\"title\">" << protectEnc(fullTitle) << "</h1>\n"; out() << "<h1 class=\"title\">" << protectEnc(fullTitle) << "</h1>\n";
const NodeList& nl = ncn->childNodes();
NodeMap nm; NodeMap nm;
NodeList::ConstIterator it = nl.begin(); for (int i=0; i<collisions.size(); ++i) {
while (it != nl.end()) { Node* n = collisions.at(i);
QString t = (*it)->qmlModuleIdentifier() + " " + protectEnc(fullTitle); QString t;
nm.insertMulti(t,(*it)); if (!n->qmlModuleIdentifier().isEmpty())
++it; t = n->qmlModuleIdentifier() + "::";
t += protectEnc(fullTitle);
nm.insertMulti(t,n);
} }
generateAnnotatedList(ncn, marker, nm, true); generateAnnotatedList(ncn, marker, nm, true);
const QMap<QString,QString>& targets = ncn->linkTargets(); QList<QString> targets;
if (!ncn->linkTargets().isEmpty()) {
QMap<QString,QString>::ConstIterator t = ncn->linkTargets().begin();
while (t != ncn->linkTargets().end()) {
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
if (n->findChildNodeByName(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
break;
}
}
}
++t;
}
}
if (!targets.isEmpty()) { if (!targets.isEmpty()) {
QMap<QString,QString>::ConstIterator t = targets.begin(); QList<QString>::ConstIterator t = targets.begin();
while (t != targets.end()) { while (t != targets.end()) {
out() << "<a name=\"" << Doc::canonicalTitle(t.key()) << "\"></a>"; out() << "<a name=\"" << Doc::canonicalTitle(*t) << "\"></a>";
out() << "<h2 class=\"title\">" << protectEnc(t.key()) << "</h2>\n"; out() << "<h2 class=\"title\">" << protectEnc(*t) << "</h2>\n";
out() << "<ul>\n"; out() << "<ul>\n";
it = nl.begin(); for (int i=0; i<collisions.size(); ++i) {
while (it != nl.end()) { InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
InnerNode* n = static_cast<InnerNode*>(*it); Node* p = n->findChildNodeByName(*t);
Node* p = n->findNode(t.key());
if (p) { if (p) {
QString link = linkForNode(p,0); QString link = linkForNode(p,0);
QString label = n->qmlModuleIdentifier() + "::" + n->name() + "::" + p->name(); QString label;
if (!n->qmlModuleIdentifier().isEmpty())
label = n->qmlModuleIdentifier() + "::";
label += n->name() + "::" + p->name();
out() << "<li>"; out() << "<li>";
out() << "<a href=\"" << link << "\">"; out() << "<a href=\"" << link << "\">";
out() << protectEnc(label) << "</a>"; out() << protectEnc(label) << "</a>";
out() << "</li>\n"; out() << "</li>\n";
} }
++it;
} }
out() << "</ul>\n"; out() << "</ul>\n";
++t; ++t;
@ -1435,7 +1471,7 @@ void HtmlGenerator::generateDisambiguationPages()
Generate the HTML page for an entity that doesn't map Generate the HTML page for an entity that doesn't map
to any underlying parsable C++ class or QML component. to any underlying parsable C++ class or QML component.
*/ */
void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) void HtmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker)
{ {
/* /*
If the fake node is a page node, and if the page type If the fake node is a page node, and if the page type
@ -1471,9 +1507,9 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
Generate the TOC for the new doc format. Generate the TOC for the new doc format.
Don't generate a TOC for the home page. Don't generate a TOC for the home page.
*/ */
const QmlClassNode* qml_cn = 0; QmlClassNode* qml_cn = 0;
if (fake->subType() == Node::QmlClass) { if (fake->subType() == Node::QmlClass) {
qml_cn = static_cast<const QmlClassNode*>(fake); qml_cn = static_cast<QmlClassNode*>(fake);
sections = marker->qmlSections(qml_cn,CodeMarker::Summary); sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
generateTableOfContents(fake,marker,&sections); generateTableOfContents(fake,marker,&sections);
@ -1537,7 +1573,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
} }
else if (fake->subType() == Node::QmlClass) { else if (fake->subType() == Node::QmlClass) {
const_cast<FakeNode*>(fake)->setCurrentChild(); const_cast<FakeNode*>(fake)->setCurrentChild();
const ClassNode* cn = qml_cn->classNode(); ClassNode* cn = qml_cn->classNode();
generateBrief(qml_cn, marker); generateBrief(qml_cn, marker);
generateQmlInherits(qml_cn, marker); generateQmlInherits(qml_cn, marker);
generateQmlInheritedBy(qml_cn, marker); generateQmlInheritedBy(qml_cn, marker);
@ -1793,7 +1829,7 @@ void HtmlGenerator::generateHeader(const QString& title,
if (node && !node->doc().location().isEmpty()) if (node && !node->doc().location().isEmpty())
out() << "<!-- " << node->doc().location().fileName() << " -->\n"; out() << "<!-- " << node->doc().location().fileName() << " -->\n";
QString shortVersion = myTree->version(); QString shortVersion = tree_->version();
if (shortVersion.count(QChar('.')) == 2) if (shortVersion.count(QChar('.')) == 2)
shortVersion.truncate(shortVersion.lastIndexOf(QChar('.'))); shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
if (!project.isEmpty()) if (!project.isEmpty())
@ -1814,9 +1850,9 @@ void HtmlGenerator::generateHeader(const QString& title,
generateMacRef(node, marker); generateMacRef(node, marker);
#endif #endif
out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); out() << QString(postHeader).replace("\\" + COMMAND_VERSION, tree_->version());
generateBreadCrumbs(title,node,marker); generateBreadCrumbs(title,node,marker);
out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, tree_->version());
navigationLinks.clear(); navigationLinks.clear();
@ -1901,8 +1937,8 @@ void HtmlGenerator::generateFooter(const Node *node)
if (node && !node->links().empty()) if (node && !node->links().empty())
out() << "<p class=\"naviNextPrevious footerNavi\">\n" << navigationLinks << "</p>\n"; out() << "<p class=\"naviNextPrevious footerNavi\">\n" << navigationLinks << "</p>\n";
out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version()) out() << QString(footer).replace("\\" + COMMAND_VERSION, tree_->version())
<< QString(address).replace("\\" + COMMAND_VERSION, myTree->version()); << QString(address).replace("\\" + COMMAND_VERSION, tree_->version());
out() << "</body>\n"; out() << "</body>\n";
out() << "</html>\n"; out() << "</html>\n";
@ -2633,7 +2669,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
QMap<QString, FakeNode *> uncategorizedNodeMap; QMap<QString, FakeNode *> uncategorizedNodeMap;
QRegExp singleDigit("\\b([0-9])\\b"); QRegExp singleDigit("\\b([0-9])\\b");
const NodeList children = myTree->root()->childNodes(); const NodeList children = tree_->root()->childNodes();
foreach (Node *child, children) { foreach (Node *child, children) {
if (child->type() == Node::Fake && child != relative) { if (child->type() == Node::Fake && child != relative) {
FakeNode *fakeNode = static_cast<FakeNode *>(child); FakeNode *fakeNode = static_cast<FakeNode *>(child);
@ -2685,15 +2721,11 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
else if (!isGroupPage) { else if (!isGroupPage) {
// If we encounter a page that belongs to a group then // If we encounter a page that belongs to a group then
// we add that page to the list for that group. // we add that page to the list for that group.
const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake)); const FakeNode* gn = tree_->findGroupNode(QStringList(group));
if (groupNode) if (gn)
fakeNodeMap[groupNode].insert(sortKey, fakeNode); fakeNodeMap[gn].insert(sortKey, fakeNode);
//else }
// uncategorizedNodeMap.insert(sortKey, fakeNode); }
}// else
// uncategorizedNodeMap.insert(sortKey, fakeNode);
}// else
// uncategorizedNodeMap.insert(sortKey, fakeNode);
} }
} }
@ -2994,7 +3026,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
const Node* n = marker->resolveTarget(par1.toString(), const Node* n = marker->resolveTarget(par1.toString(),
myTree, tree_,
relative); relative);
QString link = linkForNode(n, relative); QString link = linkForNode(n, relative);
addLink(link, arg, &html); addLink(link, arg, &html);
@ -3020,7 +3052,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
bool handled = false; bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef(); par1 = QStringRef();
const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self); const Node* n = marker->resolveTarget(arg.toString(), tree_, relative, self);
html += QLatin1String("<span class=\"type\">"); html += QLatin1String("<span class=\"type\">");
if (n && n->subType() == Node::QmlBasicType) { if (n && n->subType() == Node::QmlBasicType) {
if (relative && relative->subType() == Node::QmlClass) if (relative && relative->subType() == Node::QmlClass)
@ -3035,13 +3067,13 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
} }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef(); par1 = QStringRef();
const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); const Node* n = marker->resolveTarget(arg.toString(), tree_, relative);
addLink(linkForNode(n,relative), arg, &html); addLink(linkForNode(n,relative), arg, &html);
handled = true; handled = true;
} }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef(); par1 = QStringRef();
const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); const Node* n = marker->resolveTarget(arg.toString(), tree_, relative);
addLink(linkForNode(n,relative), arg, &html); addLink(linkForNode(n,relative), arg, &html);
handled = true; handled = true;
} }
@ -3352,8 +3384,6 @@ QString HtmlGenerator::refForNode(const Node *node)
case Node::Variable: case Node::Variable:
ref = node->name() + "-var"; ref = node->name() + "-var";
break; break;
case Node::Target:
return protectEnc(node->name());
} }
return registerRef(ref); return registerRef(ref);
} }
@ -3699,15 +3729,15 @@ const Node *HtmlGenerator::findNodeForTarget(const QString &target,
node = relative; node = relative;
} }
else if (target.endsWith(".html")) { else if (target.endsWith(".html")) {
node = myTree->root()->findNode(target, Node::Fake); node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake);
} }
else if (marker) { else if (marker) {
node = marker->resolveTarget(target, myTree, relative); node = marker->resolveTarget(target, tree_, relative);
if (!node) { if (!node) {
node = myTree->findFakeNodeByTitle(target, relative); node = tree_->findFakeNodeByTitle(target, relative);
} }
if (!node && atom) { if (!node && atom) {
node = myTree->findUnambiguousTarget(target, *const_cast<Atom**>(&atom), relative); node = tree_->findUnambiguousTarget(target, *const_cast<Atom**>(&atom), relative);
} }
} }
@ -3762,15 +3792,21 @@ QString HtmlGenerator::getLink(const Atom *atom,
*node = relative; *node = relative;
} }
else if (first.endsWith(".html")) { else if (first.endsWith(".html")) {
*node = myTree->root()->findNode(first, Node::Fake); /*
This is not a recursive search. That's ok in
this case, because we are searching for a page
node, which must be a direct child of the tree
root.
*/
*node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake);
} }
else { else {
*node = marker->resolveTarget(first, myTree, relative); *node = marker->resolveTarget(first, tree_, relative);
if (!*node) { if (!*node) {
*node = myTree->findFakeNodeByTitle(first, relative); *node = tree_->findFakeNodeByTitle(first, relative);
} }
if (!*node) { if (!*node) {
*node = myTree->findUnambiguousTarget(first, targetAtom, relative); *node = tree_->findUnambiguousTarget(first, targetAtom, relative);
} }
} }
if (*node) { if (*node) {
@ -3824,7 +3860,7 @@ QString HtmlGenerator::getLink(const Atom *atom,
target. target.
*/ */
while (!path.isEmpty()) { while (!path.isEmpty()) {
targetAtom = myTree->findTarget(path.first(), *node); targetAtom = tree_->findTarget(path.first(), *node);
if (targetAtom == 0) if (targetAtom == 0)
break; break;
path.removeFirst(); path.removeFirst();
@ -3861,44 +3897,11 @@ QString HtmlGenerator::getLink(const Atom *atom,
return link; return link;
} }
/*!
This function can be called if getLink() returns an empty
string. It tests the \a atom string to see if it is a link
of the form <element> :: <name>, where <element> is a QML
element or component without a module qualifier. If so, it
constructs a link to the <name> clause on the disambiguation
page for <element> and returns that link string. It also
adds the <name> as a target in the NameCollisionNode for
<element>. These clauses are then constructed when the
disambiguation page is actually generated.
*/
QString HtmlGenerator::getDisambiguationLink(const Atom *atom, CodeMarker *)
{
QString link;
if (!atom->string().contains("::"))
return link;
QStringList path = atom->string().split("::");
NameCollisionNode* ncn = myTree->findCollisionNode(path[0]);
if (ncn) {
QString label;
if (atom->next() && atom->next()->next()) {
if (atom->next()->type() == Atom::FormattingLeft &&
atom->next()->next()->type() == Atom::String)
label = atom->next()->next()->string();
}
ncn->addLinkTarget(path[1],label);
link = fileName(ncn);
link += QLatin1Char('#');
link += Doc::canonicalTitle(path[1]);
}
return link;
}
void HtmlGenerator::generateIndex(const QString &fileBase, void HtmlGenerator::generateIndex(const QString &fileBase,
const QString &url, const QString &url,
const QString &title) const QString &title)
{ {
myTree->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title); tree_->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title);
} }
void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
@ -3922,12 +3925,12 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
<< "We strongly advise against " << "We strongly advise against "
<< "using it in new code. See "; << "using it in new code. See ";
const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4"); const FakeNode *fakeNode = tree_->findFakeNodeByTitle("Porting To Qt 4");
Atom *targetAtom = 0; Atom *targetAtom = 0;
if (fakeNode && node->type() == Node::Class) { if (fakeNode && node->type() == Node::Class) {
QString oldName(node->name()); QString oldName(node->name());
oldName.remove(QLatin1Char('3')); oldName.remove(QLatin1Char('3'));
targetAtom = myTree->findTarget(oldName, targetAtom = tree_->findTarget(oldName,
fakeNode); fakeNode);
} }
@ -4044,11 +4047,11 @@ void HtmlGenerator::generateQmlSummary(const Section& section,
Outputs the html detailed documentation for a section Outputs the html detailed documentation for a section
on a QML element reference page. on a QML element reference page.
*/ */
void HtmlGenerator::generateDetailedQmlMember(const Node *node, void HtmlGenerator::generateDetailedQmlMember(Node *node,
const InnerNode *relative, const InnerNode *relative,
CodeMarker *marker) CodeMarker *marker)
{ {
const QmlPropertyNode* qpn = 0; QmlPropertyNode* qpn = 0;
#ifdef GENERATE_MAC_REFS #ifdef GENERATE_MAC_REFS
generateMacRef(node, marker); generateMacRef(node, marker);
#endif #endif
@ -4061,14 +4064,14 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
out() << "<table class=\"qmlname\">"; out() << "<table class=\"qmlname\">";
while (p != qpgn->childNodes().end()) { while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) { if ((*p)->type() == Node::QmlProperty) {
qpn = static_cast<const QmlPropertyNode*>(*p); qpn = static_cast<QmlPropertyNode*>(*p);
out() << "<tr valign=\"top\" class=\"odd\">"; out() << "<tr valign=\"top\" class=\"odd\">";
out() << "<td class=\"tblQmlPropNode\"><p>"; out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
int ro = qpn->getReadOnly(); int ro = qpn->getReadOnly();
if (ro < 0) { if (ro < 0) {
if (!qpn->isWritable(myTree)) { if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>"; out() << "<span class=\"qmlreadonly\">read-only</span>";
} }
} }
@ -4086,7 +4089,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
out() << "</div>"; out() << "</div>";
} }
else if (node->type() == Node::QmlProperty) { else if (node->type() == Node::QmlProperty) {
qpn = static_cast<const QmlPropertyNode*>(node); qpn = static_cast<QmlPropertyNode*>(node);
/* /*
If the QML property node has a single subproperty, If the QML property node has a single subproperty,
override, replace qpn with that override node and override, replace qpn with that override node and
@ -4095,7 +4098,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
if (qpn->qmlPropNodes().size() == 1) { if (qpn->qmlPropNodes().size() == 1) {
Node* n = qpn->qmlPropNodes().at(0); Node* n = qpn->qmlPropNodes().at(0);
if (n->type() == Node::QmlProperty) if (n->type() == Node::QmlProperty)
qpn = static_cast<const QmlPropertyNode*>(n); qpn = static_cast<QmlPropertyNode*>(n);
} }
/* /*
Now qpn either has no overrides, or it has more Now qpn either has no overrides, or it has more
@ -4110,7 +4113,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
int ro = qpn->getReadOnly(); int ro = qpn->getReadOnly();
if (ro < 0) { if (ro < 0) {
const ClassNode* cn = qpn->declarativeCppNode(); const ClassNode* cn = qpn->declarativeCppNode();
if (cn && !qpn->isWritable(myTree)) { if (cn && !qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>"; out() << "<span class=\"qmlreadonly\">read-only</span>";
} }
} }
@ -4142,7 +4145,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node,
int ro = qpn->getReadOnly(); int ro = qpn->getReadOnly();
if (ro < 0) { if (ro < 0) {
if (!qpn->isWritable(myTree)) { if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>"; out() << "<span class=\"qmlreadonly\">read-only</span>";
} }
} }
@ -4235,9 +4238,9 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* mar
If there is no class node, or if the class node status If there is no class node, or if the class node status
is set to Node::Internal, do nothing. is set to Node::Internal, do nothing.
*/ */
void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker) void HtmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker)
{ {
const ClassNode* cn = qcn->classNode(); ClassNode* cn = qcn->classNode();
if (cn && (cn->status() != Node::Internal)) { if (cn && (cn->status() != Node::Internal)) {
Text text; Text text;
text << Atom::ParaLeft; text << Atom::ParaLeft;
@ -4269,7 +4272,7 @@ void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker*
If there is no QML element, or if the class node status If there is no QML element, or if the class node status
is set to Node::Internal, do nothing. is set to Node::Internal, do nothing.
*/ */
void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker) void HtmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker)
{ {
if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) { if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) {
const QmlClassNode* qcn = cn->qmlElement(); const QmlClassNode* qcn = cn->qmlElement();
@ -4460,9 +4463,6 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node, bool subdir)
case Node::Variable: case Node::Variable:
anchorRef = QLatin1Char('#') + node->name() + "-var"; anchorRef = QLatin1Char('#') + node->name() + "-var";
break; break;
case Node::Target:
anchorRef = QLatin1Char('#') + Doc::canonicalTitle(node->name());
break;
case Node::Fake: case Node::Fake:
{ {
/* /*
@ -4753,8 +4753,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
if (!related) if (!related)
child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message)); child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message));
break; break;
case Node::Target:
break;
case Node::QmlProperty: case Node::QmlProperty:
if (!related) if (!related)
child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message)); child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message));
@ -4863,7 +4861,7 @@ void HtmlGenerator::writeDitaRefs(const DitaRefList& ditarefs)
xmlWriter().writeStartElement("topicref"); xmlWriter().writeStartElement("topicref");
xmlWriter().writeAttribute("navtitle",t->navtitle()); xmlWriter().writeAttribute("navtitle",t->navtitle());
if (t->href().isEmpty()) { if (t->href().isEmpty()) {
const FakeNode* fn = myTree->findFakeNodeByTitle(t->navtitle()); const FakeNode* fn = tree_->findFakeNodeByTitle(t->navtitle());
if (fn) if (fn)
xmlWriter().writeAttribute("href",fileName(fn)); xmlWriter().writeAttribute("href",fileName(fn));
} }

View File

@ -86,8 +86,8 @@ public:
virtual void initializeGenerator(const Config& config); virtual void initializeGenerator(const Config& config);
virtual void terminateGenerator(); virtual void terminateGenerator();
virtual QString format(); virtual QString format();
virtual void generateTree(const Tree *tree); virtual void generateTree(Tree *tree);
virtual void generateDisambiguationPages(); void generateCollisionPages();
void generateManifestFiles(); void generateManifestFiles();
QString protectEnc(const QString &string); QString protectEnc(const QString &string);
@ -101,8 +101,8 @@ protected:
virtual int generateAtom(const Atom *atom, virtual int generateAtom(const Atom *atom,
const Node *relative, const Node *relative,
CodeMarker *marker); CodeMarker *marker);
virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual QString fileExtension(const Node *node) const; virtual QString fileExtension(const Node *node) const;
virtual QString refForNode(const Node *node); virtual QString refForNode(const Node *node);
virtual QString linkForNode(const Node *node, const Node *relative); virtual QString linkForNode(const Node *node, const Node *relative);
@ -176,12 +176,12 @@ private:
const Node *relative, const Node *relative,
CodeMarker *marker, CodeMarker *marker,
bool summary); bool summary);
void generateDetailedQmlMember(const Node *node, void generateDetailedQmlMember(Node *node,
const InnerNode *relative, const InnerNode *relative,
CodeMarker *marker); CodeMarker *marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
void generateSection(const NodeList& nl, void generateSection(const NodeList& nl,
const Node *relative, const Node *relative,
@ -227,7 +227,6 @@ private:
const Node *relative, const Node *relative,
CodeMarker *marker, CodeMarker *marker,
const Node** node); const Node** node);
QString getDisambiguationLink(const Atom* atom, CodeMarker* marker);
virtual void generateIndex(const QString &fileBase, virtual void generateIndex(const QString &fileBase,
const QString &url, const QString &url,
const QString &title); const QString &title);
@ -278,7 +277,6 @@ private:
QString manifestDir; QString manifestDir;
QStringList stylesheets; QStringList stylesheets;
QStringList customHeadElements; QStringList customHeadElements;
const Tree *myTree;
bool obsoleteLinks; bool obsoleteLinks;
QMap<QString, NodeMap > moduleClassMap; QMap<QString, NodeMap > moduleClassMap;
QMap<QString, NodeMap > moduleNamespaceMap; QMap<QString, NodeMap > moduleNamespaceMap;

View File

@ -237,8 +237,6 @@ QString Node::nodeTypeString(unsigned t)
return "property"; return "property";
case Variable: case Variable:
return "variable"; return "variable";
case Target:
return "target";
case QmlProperty: case QmlProperty:
return "QML property"; return "QML property";
case QmlSignal: case QmlSignal:
@ -524,14 +522,14 @@ QString Node::ditaXmlHref()
If it is a child of a QML class node, return a pointer to If it is a child of a QML class node, return a pointer to
the QML class node. Otherwise, return 0; the QML class node. Otherwise, return 0;
*/ */
const QmlClassNode* Node::qmlClassNode() const QmlClassNode* Node::qmlClassNode()
{ {
if (isQmlNode()) { if (isQmlNode()) {
const Node* n = this; Node* n = this;
while (n && n->subType() != Node::QmlClass) while (n && n->subType() != Node::QmlClass)
n = n->parent(); n = n->parent();
if (n && n->subType() == Node::QmlClass) if (n && n->subType() == Node::QmlClass)
return static_cast<const QmlClassNode*>(n); return static_cast<QmlClassNode*>(n);
} }
return 0; return 0;
} }
@ -543,14 +541,29 @@ const QmlClassNode* Node::qmlClassNode() const
class node is a component. It will be non-null if class node is a component. It will be non-null if
the QML class node is a QML element. the QML class node is a QML element.
*/ */
const ClassNode* Node::declarativeCppNode() const ClassNode* Node::declarativeCppNode()
{ {
const QmlClassNode* qcn = qmlClassNode(); QmlClassNode* qcn = qmlClassNode();
if (qcn) if (qcn)
return qcn->classNode(); return qcn->classNode();
return 0; return 0;
} }
/*!
Returns true if the node's status is Internal, or if its
parent is a class with internal status.
*/
bool Node::isInternal() const
{
if (status() == Internal)
return true;
if (parent() && parent()->status() == Internal)
return true;
if (relates() && relates()->status() == Internal)
return true;
return false;
}
/*! /*!
\class InnerNode \class InnerNode
*/ */
@ -571,7 +584,7 @@ InnerNode::~InnerNode()
sure to also look in the children of its property sure to also look in the children of its property
group nodes. Return the matching node or 0. group nodes. Return the matching node or 0.
*/ */
Node *InnerNode::findNode(const QString& name) Node *InnerNode::findChildNodeByName(const QString& name)
{ {
Node *node = childMap.value(name); Node *node = childMap.value(name);
if (node && node->subType() != QmlPropertyGroup) if (node && node->subType() != QmlPropertyGroup)
@ -580,7 +593,7 @@ Node *InnerNode::findNode(const QString& name)
for (int i=0; i<children.size(); ++i) { for (int i=0; i<children.size(); ++i) {
Node* n = children.at(i); Node* n = children.at(i);
if (n->subType() == QmlPropertyGroup) { if (n->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(n)->findNode(name); node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
if (node) if (node)
return node; return node;
} }
@ -604,7 +617,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
for (int i=0; i<children.size(); ++i) { for (int i=0; i<children.size(); ++i) {
node = children.at(i); node = children.at(i);
if (node->subType() == QmlPropertyGroup) { if (node->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findNode(name); node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) { if (node) {
n.append(node); n.append(node);
return; return;
@ -628,7 +641,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
if (node->subType() != QmlPropertyGroup) if (node->subType() != QmlPropertyGroup)
n.append(node); n.append(node);
else { else {
node = static_cast<InnerNode*>(node)->findNode(name); node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) if (node)
n.append(node); n.append(node);
} }
@ -644,13 +657,14 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
/*! /*!
Find the node in this node's children that has the given \a name. If Find the node in this node's children that has the given \a name. If
this node is a QML class node, be sure to also look in the children this node is a QML class node, be sure to also look in the children
of its property group nodes. Return the matching node or 0. of its property group nodes. Return the matching node or 0. This is
not a recearsive search.
If \a qml is true, only match a node for which node->isQmlNode() If \a qml is true, only match a node for which node->isQmlNode()
returns true. If \a qml is false, only match a node for which returns true. If \a qml is false, only match a node for which
node->isQmlNode() returns false. node->isQmlNode() returns false.
*/ */
Node* InnerNode::findNode(const QString& name, bool qml) Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
{ {
QList<Node*> nodes = childMap.values(name); QList<Node*> nodes = childMap.values(name);
if (!nodes.isEmpty()) { if (!nodes.isEmpty()) {
@ -668,7 +682,7 @@ Node* InnerNode::findNode(const QString& name, bool qml)
for (int i=0; i<children.size(); ++i) { for (int i=0; i<children.size(); ++i) {
Node* node = children.at(i); Node* node = children.at(i);
if (node->subType() == QmlPropertyGroup) { if (node->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findNode(name); node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) if (node)
return node; return node;
} }
@ -678,28 +692,31 @@ Node* InnerNode::findNode(const QString& name, bool qml)
} }
/*! /*!
Same as the other findNode(), but if the node with the This function is like findChildNodeByName(), but if a node
specified \a name is not of the specified \a type, return with the specified \a name is found but it is not of the
0. specified \a type, 0 is returned.
This function is not recursive and therefore can't handle
collisions. If it finds a collision node named \a name, it
will return that node. But it might not find the collision
node because it looks up \a name in the child map, not the
list.
*/ */
Node *InnerNode::findNode(const QString& name, Type type) Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
{ {
if (type == Function) { if (type == Function)
return primaryFunctionMap.value(name); return primaryFunctionMap.value(name);
}
else { else {
Node *node = childMap.value(name); Node *node = childMap.value(name);
if (node && node->type() == type) { if (node && node->type() == type)
return node; return node;
}
else {
return 0;
}
} }
return 0;
} }
/*! /*!
Find the function node in this node for the function named \a name. Find a function node that is a child of this nose, such
that the function node has the specified \a name.
*/ */
FunctionNode *InnerNode::findFunctionNode(const QString& name) FunctionNode *InnerNode::findFunctionNode(const QString& name)
{ {
@ -707,12 +724,13 @@ FunctionNode *InnerNode::findFunctionNode(const QString& name)
} }
/*! /*!
Find the function node in this node that has the same name as \a clone. Find the function node that is a child of this node, such
that the function has the same name and signature as the
\a clone node.
*/ */
FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone)
{ {
QMap<QString, Node *>::ConstIterator c = QMap<QString,Node*>::ConstIterator c = primaryFunctionMap.find(clone->name());
primaryFunctionMap.find(clone->name());
if (c != primaryFunctionMap.end()) { if (c != primaryFunctionMap.end()) {
if (isSameSignature(clone, (FunctionNode *) *c)) { if (isSameSignature(clone, (FunctionNode *) *c)) {
return (FunctionNode *) *c; return (FunctionNode *) *c;
@ -907,10 +925,10 @@ void InnerNode::deleteChildren()
/*! /*!
*/ */
const Node *InnerNode::findNode(const QString& name) const const Node *InnerNode::findChildNodeByName(const QString& name) const
{ {
InnerNode *that = (InnerNode *) this; InnerNode *that = (InnerNode *) this;
return that->findNode(name); return that->findChildNodeByName(name);
} }
/*! /*!
@ -918,22 +936,26 @@ const Node *InnerNode::findNode(const QString& name) const
returns true. If \a qml is false, only match a node for which returns true. If \a qml is false, only match a node for which
node->isQmlNode() returns false. node->isQmlNode() returns false.
*/ */
const Node* InnerNode::findNode(const QString& name, bool qml) const const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
{ {
InnerNode*that = (InnerNode*) this; InnerNode*that = (InnerNode*) this;
return that->findNode(name, qml); return that->findChildNodeByName(name, qml);
} }
/*! /*!
Searches this node's children for a child named \a name
with the specified node \a type.
*/ */
const Node *InnerNode::findNode(const QString& name, Type type) const const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const
{ {
InnerNode *that = (InnerNode *) this; InnerNode *that = (InnerNode *) this;
return that->findNode(name, type); return that->findChildNodeByNameAndType(name, type);
} }
/*! /*!
Find the function node in this node that has the given \a name. Find a function node that is a child of this nose, such
that the function node has the specified \a name. This
function calls the non-const version of itself.
*/ */
const FunctionNode *InnerNode::findFunctionNode(const QString& name) const const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{ {
@ -942,7 +964,9 @@ const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
} }
/*! /*!
Find the function node in this node that has the same name as \a clone. Find the function node that is a child of this node, such
that the function has the same name and signature as the
\a clone node. This function calls the non-const version.
*/ */
const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
{ {
@ -1196,13 +1220,9 @@ void InnerNode::removeRelated(Node *pseudoChild)
\class LeafNode \class LeafNode
*/ */
/*! /*! \fn bool LeafNode::isInnerNode() const
Returns false because this is a LeafNode. Returns false because this is a LeafNode.
*/ */
bool LeafNode::isInnerNode() const
{
return false;
}
/*! /*!
Constructs a leaf node named \a name of the specified Constructs a leaf node named \a name of the specified
@ -1339,19 +1359,19 @@ void ClassNode::fixBaseClasses()
Search the child list to find the property node with the Search the child list to find the property node with the
specified \a name. specified \a name.
*/ */
const PropertyNode *ClassNode::findPropertyNode(const QString &name) const PropertyNode* ClassNode::findPropertyNode(const QString& name)
{ {
const Node *n = findNode(name, Node::Property); Node* n = findChildNodeByNameAndType(name, Node::Property);
if (n) if (n)
return static_cast<const PropertyNode*>(n); return static_cast<PropertyNode*>(n);
const PropertyNode *pn = 0; PropertyNode* pn = 0;
const QList<RelatedClass> &bases = baseClasses(); const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) { if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) { for (int i = 0; i < bases.size(); ++i) {
const ClassNode *cn = bases[i].node; ClassNode* cn = bases[i].node;
pn = cn->findPropertyNode(name); pn = cn->findPropertyNode(name);
if (pn) if (pn)
break; break;
@ -1360,7 +1380,7 @@ const PropertyNode *ClassNode::findPropertyNode(const QString &name) const
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses(); const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) { if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) { for (int i = 0; i < ignoredBases.size(); ++i) {
const ClassNode *cn = ignoredBases[i].node; ClassNode* cn = ignoredBases[i].node;
pn = cn->findPropertyNode(name); pn = cn->findPropertyNode(name);
if (pn) if (pn)
break; break;
@ -1376,20 +1396,20 @@ const PropertyNode *ClassNode::findPropertyNode(const QString &name) const
finds one, it returns the pointer to that QML element. If finds one, it returns the pointer to that QML element. If
it doesn't find one, it returns null. it doesn't find one, it returns null.
*/ */
const QmlClassNode* ClassNode::findQmlBaseNode() const QmlClassNode* ClassNode::findQmlBaseNode()
{ {
const QmlClassNode* result = 0; QmlClassNode* result = 0;
const QList<RelatedClass>& bases = baseClasses(); const QList<RelatedClass>& bases = baseClasses();
if (!bases.isEmpty()) { if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) { for (int i = 0; i < bases.size(); ++i) {
const ClassNode* cn = bases[i].node; ClassNode* cn = bases[i].node;
if (cn && cn->qmlElement()) { if (cn && cn->qmlElement()) {
return cn->qmlElement(); return cn->qmlElement();
} }
} }
for (int i = 0; i < bases.size(); ++i) { for (int i = 0; i < bases.size(); ++i) {
const ClassNode* cn = bases[i].node; ClassNode* cn = bases[i].node;
if (cn) { if (cn) {
result = cn->findQmlBaseNode(); result = cn->findQmlBaseNode();
if (result != 0) { if (result != 0) {
@ -1467,12 +1487,15 @@ QString FakeNode::fullTitle() const
else else
return title(); return title();
} }
else if ((nodeSubtype_ == HeaderFile) || (nodeSubtype_ == Collision)) { else if (nodeSubtype_ == HeaderFile) {
if (title().isEmpty()) if (title().isEmpty())
return name(); return name();
else else
return name() + " - " + title(); return name() + " - " + title();
} }
else if (nodeSubtype_ == Collision) {
return title();
}
else { else {
return title(); return title();
} }
@ -1832,21 +1855,6 @@ QString FunctionNode::signature(bool values) const
return s; return s;
} }
/*!
Returns true if the node's status is Internal, or if its
parent is a class with internal status.
*/
bool FunctionNode::isInternal() const
{
if (status() == Internal)
return true;
if (parent() && parent()->status() == Internal)
return true;
if (relates() && relates()->status() == Internal)
return true;
return false;
}
/*! /*!
Print some debugging stuff. Print some debugging stuff.
*/ */
@ -1964,25 +1972,6 @@ bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
} }
} }
/*!
\class TargetNode
*/
/*!
*/
TargetNode::TargetNode(InnerNode *parent, const QString& name)
: LeafNode(Target, parent, name)
{
}
/*!
Returns false because this is a TargetNode.
*/
bool TargetNode::isInnerNode() const
{
return false;
}
bool QmlClassNode::qmlOnly = false; bool QmlClassNode::qmlOnly = false;
QMultiMap<QString,Node*> QmlClassNode::inheritedBy; QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
QMap<QString, QmlClassNode*> QmlClassNode::moduleMap; QMap<QString, QmlClassNode*> QmlClassNode::moduleMap;
@ -1996,7 +1985,7 @@ QMap<QString, QmlClassNode*> QmlClassNode::moduleMap;
*/ */
QmlClassNode::QmlClassNode(InnerNode *parent, QmlClassNode::QmlClassNode(InnerNode *parent,
const QString& name, const QString& name,
const ClassNode* cn) ClassNode* cn)
: FakeNode(parent, name, QmlClass, Node::ApiPage), : FakeNode(parent, name, QmlClass, Node::ApiPage),
abstract(false), abstract(false),
cnode_(cn), cnode_(cn),
@ -2132,15 +2121,15 @@ void QmlClassNode::clearCurrentChild()
to output the line in the documentation that specifies the to output the line in the documentation that specifies the
QML element that a QML element inherits. QML element that a QML element inherits.
*/ */
void QmlClassNode::resolveInheritance(const Tree* tree) void QmlClassNode::resolveInheritance(Tree* tree)
{ {
if (!links().empty() && links().contains(Node::InheritsLink)) { if (!links().empty() && links().contains(Node::InheritsLink)) {
QPair<QString,QString> linkPair; QPair<QString,QString> linkPair;
linkPair = links()[Node::InheritsLink]; linkPair = links()[Node::InheritsLink];
QStringList strList = linkPair.first.split("::"); QStringList strList = linkPair.first.split("::");
const Node* n = tree->findNode(strList,Node::Fake); Node* n = tree->findQmlClassNode(strList);
if (n && (n->subType() == Node::QmlClass || n->subType() == Node::Collision)) { if (n) {
base_ = static_cast<const FakeNode*>(n); base_ = static_cast<FakeNode*>(n);
if (base_ && base_->subType() == Node::QmlClass) { if (base_ && base_->subType() == Node::QmlClass) {
return; return;
} }
@ -2152,7 +2141,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree)
QString qmid = importList_.at(i).first + importList_.at(i).second; QString qmid = importList_.at(i).first + importList_.at(i).second;
for (int j=0; j<children.size(); ++j) { for (int j=0; j<children.size(); ++j) {
if (qmid == children.at(j)->qmlModuleIdentifier()) { if (qmid == children.at(j)->qmlModuleIdentifier()) {
base_ = static_cast<const FakeNode*>(children.at(j)); base_ = static_cast<FakeNode*>(children.at(j));
return; return;
} }
} }
@ -2160,7 +2149,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree)
QString qmid = qmlModuleIdentifier(); QString qmid = qmlModuleIdentifier();
for (int k=0; k<children.size(); ++k) { for (int k=0; k<children.size(); ++k) {
if (qmid == children.at(k)->qmlModuleIdentifier()) { if (qmid == children.at(k)->qmlModuleIdentifier()) {
base_ = static_cast<const QmlClassNode*>(children.at(k)); base_ = static_cast<QmlClassNode*>(children.at(k));
return; return;
} }
} }
@ -2169,7 +2158,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree)
return; return;
} }
if (cnode_) { if (cnode_) {
const QmlClassNode* qcn = cnode_->findQmlBaseNode(); QmlClassNode* qcn = cnode_->findQmlBaseNode();
if (qcn != 0) if (qcn != 0)
base_ = qcn; base_ = qcn;
} }
@ -2302,12 +2291,12 @@ bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue)
doesn't work for qmlproperty bool PropertyChanges::explicit, doesn't work for qmlproperty bool PropertyChanges::explicit,
because the tokenizer gets confused on "explicit". because the tokenizer gets confused on "explicit".
*/ */
bool QmlPropertyNode::isWritable(const Tree* tree) const bool QmlPropertyNode::isWritable(Tree* tree)
{ {
if (wri != Trool_Default) if (wri != Trool_Default)
return fromTrool(wri, false); return fromTrool(wri, false);
const PropertyNode *pn = correspondingProperty(tree); PropertyNode* pn = correspondingProperty(tree);
if (pn) if (pn)
return pn->isWritable(); return pn->isWritable();
else { else {
@ -2316,16 +2305,16 @@ bool QmlPropertyNode::isWritable(const Tree* tree) const
} }
} }
const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) const PropertyNode* QmlPropertyNode::correspondingProperty(Tree *tree)
{ {
const PropertyNode *pn; PropertyNode* pn;
Node* n = parent(); Node* n = parent();
while (n && n->subType() != Node::QmlClass) while (n && n->subType() != Node::QmlClass)
n = n->parent(); n = n->parent();
if (n) { if (n) {
const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n); QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
const ClassNode* cn = qcn->classNode(); ClassNode* cn = qcn->classNode();
if (cn) { if (cn) {
QStringList dotSplit = name().split(QChar('.')); QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]); pn = cn->findPropertyNode(dotSplit[0]);
@ -2335,10 +2324,10 @@ const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) con
// the property group, <group>.<property>. // the property group, <group>.<property>.
QStringList path(extractClassName(pn->qualifiedDataType())); QStringList path(extractClassName(pn->qualifiedDataType()));
const Node* nn = tree->findNode(path,Class); Node* nn = tree->findClassNode(path);
if (nn) { if (nn) {
const ClassNode* cn = static_cast<const ClassNode*>(nn); ClassNode* cn = static_cast<ClassNode*>(nn);
const PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]); PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
if (pn2) if (pn2)
return pn2; // Return the property for the QML property. return pn2; // Return the property for the QML property.
else else
@ -2374,7 +2363,7 @@ const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) con
NameCollisionNode::NameCollisionNode(InnerNode* child) NameCollisionNode::NameCollisionNode(InnerNode* child)
: FakeNode(child->parent(), child->name(), Collision, Node::NoPageType) : FakeNode(child->parent(), child->name(), Collision, Node::NoPageType)
{ {
setTitle("Name Collisions For: " + child->name()); setTitle("Name Collision: " + child->name());
addCollision(child); addCollision(child);
current = 0; current = 0;
} }
@ -2431,7 +2420,7 @@ bool NameCollisionNode::isQmlNode() const
Find any of this collision node's children that has type \a t Find any of this collision node's children that has type \a t
and subtype \a st and return a pointer to it. and subtype \a st and return a pointer to it.
*/ */
const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
{ {
if (current) { if (current) {
if (current->type() == t && current->subType() == st) if (current->type() == t && current->subType() == st)
@ -2441,7 +2430,7 @@ const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) cons
NodeList::ConstIterator i = cn.begin(); NodeList::ConstIterator i = cn.begin();
while (i != cn.end()) { while (i != cn.end()) {
if ((*i)->type() == t && (*i)->subType() == st) if ((*i)->type() == t && (*i)->subType() == st)
return static_cast<const InnerNode*>(*i); return static_cast<InnerNode*>(*i);
++i; ++i;
} }
return 0; return 0;
@ -2756,9 +2745,6 @@ QString Node::idForNode() const
case Node::Variable: case Node::Variable:
str = "var-" + name(); str = "var-" + name();
break; break;
case Node::Target:
str = name();
break;
default: default:
qDebug() << "ERROR: A case was not handled in Node::idForNode():" qDebug() << "ERROR: A case was not handled in Node::idForNode():"
<< "type():" << type() << "subType():" << subType(); << "type():" << type() << "subType():" << subType();

View File

@ -83,7 +83,6 @@ public:
Function, Function,
Property, Property,
Variable, Variable,
Target,
QmlProperty, QmlProperty,
QmlSignal, QmlSignal,
QmlSignalHandler, QmlSignalHandler,
@ -177,14 +176,17 @@ public:
virtual void setOutputFileName(const QString& ) { } virtual void setOutputFileName(const QString& ) { }
virtual bool isInnerNode() const = 0; virtual bool isInnerNode() const = 0;
virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; } virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
virtual bool isQmlNode() const { return false; } virtual bool isQmlNode() const { return false; }
virtual bool isInternal() const { return false; }
virtual bool isQtQuickNode() const { return false; } virtual bool isQtQuickNode() const { return false; }
virtual bool isAbstract() const { return false; } virtual bool isAbstract() const { return false; }
virtual bool isQmlPropertyGroup() const { return false; }
virtual bool isCollisionNode() const { return false; }
virtual void setAbstract(bool ) { } virtual void setAbstract(bool ) { }
virtual QString title() const { return QString(); } virtual QString title() const { return QString(); }
bool isInternal() const;
bool isIndexNode() const { return indexNodeFlag_; } bool isIndexNode() const { return indexNodeFlag_; }
Type type() const { return nodeType_; } Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; } virtual SubType subType() const { return NoSubType; }
@ -196,6 +198,8 @@ public:
QString url() const; QString url() const;
virtual QString nameForLists() const { return name_; } virtual QString nameForLists() const { return name_; }
virtual QString outputFileName() const { return QString(); } virtual QString outputFileName() const { return QString(); }
virtual void addGroupMember(Node* ) { }
virtual void addQmlModuleMember(Node* ) { }
Access access() const { return access_; } Access access() const { return access_; }
QString accessString() const; QString accessString() const;
@ -223,13 +227,13 @@ public:
virtual QString qmlModuleVersion() const { return qmlModuleVersion_; } virtual QString qmlModuleVersion() const { return qmlModuleVersion_; }
virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersion_; } virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersion_; }
virtual void setQmlModuleName(const QString& ); virtual void setQmlModuleName(const QString& );
virtual const ClassNode* classNode() const { return 0; } virtual ClassNode* classNode() { return 0; }
virtual void clearCurrentChild() { } virtual void clearCurrentChild() { }
virtual const ImportList* importList() const { return 0; } virtual const ImportList* importList() const { return 0; }
virtual void setImportList(const ImportList& ) { } virtual void setImportList(const ImportList& ) { }
virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; } virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; }
const QmlClassNode* qmlClassNode() const; QmlClassNode* qmlClassNode();
const ClassNode* declarativeCppNode() const; ClassNode* declarativeCppNode();
const QString& outputSubdirectory() const { return outSubDir_; } const QString& outputSubdirectory() const { return outSubDir_; }
QString fullDocumentName() const; QString fullDocumentName() const;
static QString cleanId(QString str); static QString cleanId(QString str);
@ -290,9 +294,9 @@ class InnerNode : public Node
public: public:
virtual ~InnerNode(); virtual ~InnerNode();
Node* findNode(const QString& name); Node* findChildNodeByName(const QString& name);
Node* findNode(const QString& name, bool qml); Node* findChildNodeByName(const QString& name, bool qml);
Node* findNode(const QString& name, Type type); Node* findChildNodeByNameAndType(const QString& name, Type type);
void findNodes(const QString& name, QList<Node*>& n); void findNodes(const QString& name, QList<Node*>& n);
FunctionNode* findFunctionNode(const QString& name); FunctionNode* findFunctionNode(const QString& name);
FunctionNode* findFunctionNode(const FunctionNode* clone); FunctionNode* findFunctionNode(const FunctionNode* clone);
@ -306,9 +310,10 @@ public:
void removeFromRelated(); void removeFromRelated();
virtual bool isInnerNode() const { return true; } virtual bool isInnerNode() const { return true; }
const Node* findNode(const QString& name) const; virtual bool isLeaf() const { return false; }
const Node* findNode(const QString& name, bool qml) const; const Node* findChildNodeByName(const QString& name) const;
const Node* findNode(const QString& name, Type type) const; const Node* findChildNodeByName(const QString& name, bool qml) const;
const Node* findChildNodeByNameAndType(const QString& name, Type type) const;
const FunctionNode* findFunctionNode(const QString& name) const; const FunctionNode* findFunctionNode(const QString& name) const;
const FunctionNode* findFunctionNode(const FunctionNode* clone) const; const FunctionNode* findFunctionNode(const FunctionNode* clone) const;
const EnumNode* findEnumNodeForValue(const QString &enumValue) const; const EnumNode* findEnumNodeForValue(const QString &enumValue) const;
@ -358,7 +363,8 @@ public:
LeafNode(); LeafNode();
virtual ~LeafNode() { } virtual ~LeafNode() { }
virtual bool isInnerNode() const; virtual bool isInnerNode() const { return false; }
virtual bool isLeaf() const { return true; }
protected: protected:
LeafNode(Type type, InnerNode* parent, const QString& name); LeafNode(Type type, InnerNode* parent, const QString& name);
@ -412,12 +418,12 @@ public:
QString serviceName() const { return sname; } QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; } void setServiceName(const QString& value) { sname = value; }
const QmlClassNode* qmlElement() const { return qmlelement; } QmlClassNode* qmlElement() { return qmlelement; }
void setQmlElement(QmlClassNode* qcn) { qmlelement = qcn; } void setQmlElement(QmlClassNode* qcn) { qmlelement = qcn; }
virtual bool isAbstract() const { return abstract; } virtual bool isAbstract() const { return abstract; }
virtual void setAbstract(bool b) { abstract = b; } virtual void setAbstract(bool b) { abstract = b; }
const PropertyNode* findPropertyNode(const QString& name) const; PropertyNode* findPropertyNode(const QString& name);
const QmlClassNode* findQmlBaseNode() const; QmlClassNode* findQmlBaseNode();
private: private:
QList<RelatedClass> bases; QList<RelatedClass> bases;
@ -441,8 +447,8 @@ public:
void setTitle(const QString &title) { title_ = title; } void setTitle(const QString &title) { title_ = title; }
void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; } void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
void addGroupMember(Node* node) { nodeList.append(node); } virtual void addGroupMember(Node* node) { nodeList.append(node); }
void addQmlModuleMember(Node* node) { nodeList.append(node); } virtual void addQmlModuleMember(Node* node) { nodeList.append(node); }
SubType subType() const { return nodeSubtype_; } SubType subType() const { return nodeSubtype_; }
virtual QString title() const; virtual QString title() const;
@ -453,6 +459,7 @@ public:
const NodeList& qmlModuleMembers() const { return nodeList; } const NodeList& qmlModuleMembers() const { return nodeList; }
virtual QString nameForLists() const { return title(); } virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { } virtual void setImageFileName(const QString& ) { }
virtual bool isQmlPropertyGroup() const { return (nodeSubtype_ == QmlPropertyGroup); }
protected: protected:
SubType nodeSubtype_; SubType nodeSubtype_;
@ -470,8 +477,9 @@ public:
virtual void setCurrentChild(InnerNode* child) { current = child; } virtual void setCurrentChild(InnerNode* child) { current = child; }
virtual void clearCurrentChild() { current = 0; } virtual void clearCurrentChild() { current = 0; }
virtual bool isQmlNode() const; virtual bool isQmlNode() const;
virtual bool isCollisionNode() const { return true; }
virtual const Node* applyModuleIdentifier(const Node* origin) const; virtual const Node* applyModuleIdentifier(const Node* origin) const;
const InnerNode* findAny(Node::Type t, Node::SubType st) const; InnerNode* findAny(Node::Type t, Node::SubType st);
void addCollision(InnerNode* child); void addCollision(InnerNode* child);
const QMap<QString,QString>& linkTargets() const { return targets; } const QMap<QString,QString>& linkTargets() const { return targets; }
void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); } void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); }
@ -503,11 +511,11 @@ class QmlClassNode : public FakeNode
public: public:
QmlClassNode(InnerNode* parent, QmlClassNode(InnerNode* parent,
const QString& name, const QString& name,
const ClassNode* cn); ClassNode* cn);
virtual ~QmlClassNode(); virtual ~QmlClassNode();
virtual bool isQmlNode() const { return true; } virtual bool isQmlNode() const { return true; }
virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); } virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); }
virtual const ClassNode* classNode() const { return cnode_; } virtual ClassNode* classNode() { return cnode_; }
virtual QString fileBase() const; virtual QString fileBase() const;
virtual void setCurrentChild(); virtual void setCurrentChild();
virtual void clearCurrentChild(); virtual void clearCurrentChild();
@ -516,7 +524,7 @@ public:
virtual bool isAbstract() const { return abstract; } virtual bool isAbstract() const { return abstract; }
virtual void setAbstract(bool b) { abstract = b; } virtual void setAbstract(bool b) { abstract = b; }
const FakeNode* qmlBase() const { return base_; } const FakeNode* qmlBase() const { return base_; }
void resolveInheritance(const Tree* tree); void resolveInheritance(Tree* tree);
static void addInheritedBy(const QString& base, Node* sub); static void addInheritedBy(const QString& base, Node* sub);
static void subclasses(const QString& base, NodeList& subs); static void subclasses(const QString& base, NodeList& subs);
static void terminate(); static void terminate();
@ -528,8 +536,8 @@ public:
private: private:
bool abstract; bool abstract;
const ClassNode* cnode_; ClassNode* cnode_;
const FakeNode* base_; FakeNode* base_;
ImportList importList_; ImportList importList_;
}; };
@ -601,7 +609,7 @@ public:
bool isDefault() const { return isdefault_; } bool isDefault() const { return isdefault_; }
bool isStored() const { return fromTrool(sto,true); } bool isStored() const { return fromTrool(sto,true); }
bool isDesignable() const { return fromTrool(des,false); } bool isDesignable() const { return fromTrool(des,false); }
bool isWritable(const Tree* tree) const; bool isWritable(Tree* tree);
bool isAttached() const { return attached_; } bool isAttached() const { return attached_; }
bool isReadOnly() const { return (readOnly_ > 0); } bool isReadOnly() const { return (readOnly_ > 0); }
virtual bool isQmlNode() const { return true; } virtual bool isQmlNode() const { return true; }
@ -610,7 +618,7 @@ public:
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); } virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); } virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
const PropertyNode *correspondingProperty(const Tree *tree) const; PropertyNode* correspondingProperty(Tree* tree);
const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); } const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); } void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); }
@ -784,7 +792,6 @@ public:
QString signature(bool values = false) const; QString signature(bool values = false) const;
const QString& element() const { return parent()->name(); } const QString& element() const { return parent()->name(); }
bool isAttached() const { return attached_; } bool isAttached() const { return attached_; }
virtual bool isInternal() const;
virtual bool isQmlNode() const { virtual bool isQmlNode() const {
return ((type() == QmlSignal) || return ((type() == QmlSignal) ||
(type() == QmlMethod) || (type() == QmlMethod) ||
@ -945,15 +952,6 @@ inline VariableNode::VariableNode(InnerNode* parent, const QString &name)
// nothing. // nothing.
} }
class TargetNode : public LeafNode
{
public:
TargetNode(InnerNode* parent, const QString& name);
virtual ~TargetNode() { }
virtual bool isInnerNode() const;
};
class DitaMapNode : public FakeNode class DitaMapNode : public FakeNode
{ {
public: public:

View File

@ -124,18 +124,7 @@ Tree::~Tree()
delete priv; delete priv;
} }
/*! // 1 calls 2
This function simply calls the const version of itself and
returns the result.
*/
Node* Tree::findNode(const QStringList& path, Node* relative, int findFlags, const Node* self)
{
return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
relative,
findFlags,
self));
}
/*! /*!
Searches the tree for a node that matches the \a path. The Searches the tree for a node that matches the \a path. The
search begins at \a start but can move up the parent chain search begins at \a start but can move up the parent chain
@ -162,16 +151,16 @@ const Node* Tree::findNode(const QStringList& path,
return n; return n;
} }
// 2 is private; it is only called by 1.
/*! /*!
This code in this function was extracted from the other This overload function was extracted from the one above that has the
version of findNode() that has the same signature without same signature without the last bool parameter, \a qml. This version
the last bool parameter \a qml. This function is called is called only by that other one. It is therefore private. It can
only by that other findNode(). It can be called a second be called a second time by that other version, if the first call
time if the first call returns null. If \a qml is false, returns null. If \a qml is false, the search will only match a node
the search will only match a node that is not a QML node. that is not a QML node. If \a qml is true, the search will only
If \a qml is true, the search will only match a node that match a node that is a QML node.
is a QML node. */
*/
const Node* Tree::findNode(const QStringList& path, const Node* Tree::findNode(const QStringList& path,
const Node* start, const Node* start,
int findFlags, int findFlags,
@ -204,7 +193,7 @@ const Node* Tree::findNode(const QStringList& path,
if (node == 0 || !node->isInnerNode()) if (node == 0 || !node->isInnerNode())
break; break;
const Node* next = static_cast<const InnerNode*>(node)->findNode(path.at(i), qml); const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i)); next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
@ -212,10 +201,9 @@ const Node* Tree::findNode(const QStringList& path,
if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) { if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node)); NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) { foreach (const Node* baseClass, baseClasses) {
next = static_cast<const InnerNode*>(baseClass)->findNode(path.at(i)); next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1) if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass) next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
->findEnumNodeForValue(path.at(i));
if (next) if (next)
break; break;
} }
@ -238,45 +226,6 @@ const Node* Tree::findNode(const QStringList& path,
return 0; return 0;
} }
/*!
Find the node with the specified \a path name of the
specified \a type.
*/
Node* Tree::findNode(const QStringList& path,
Node::Type type,
Node* relative,
int findFlags)
{
return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
type,
relative,
findFlags));
}
/*!
This function just calls the const version of itself and returns
a pointer to the QML class node, or null.
*/
QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& element)
{
return const_cast<QmlClassNode*>(const_cast<const Tree*>(this)->findQmlClassNode(module, element));
}
/*!
Find the node with the specified \a path name of the
specified \a type.
*/
const Node* Tree::findNode(const QStringList& path,
Node::Type type,
const Node* relative,
int findFlags) const
{
const Node* node = findNode(path, relative, findFlags);
if (node != 0 && node->type() == type)
return node;
return 0;
}
/*! /*!
Find the QML class node for the specified \a module and \a name Find the QML class node for the specified \a module and \a name
identifiers. The \a module identifier may be empty. If the module identifiers. The \a module identifier may be empty. If the module
@ -286,17 +235,17 @@ const Node* Tree::findNode(const QStringList& path,
child is a QML class. If the collision node does not have a child child is a QML class. If the collision node does not have a child
that is a QML class node, return 0. that is a QML class node, return 0.
*/ */
const QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name) const QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name)
{ {
if (module.isEmpty()) { if (module.isEmpty()) {
const Node* n = findNode(QStringList(name), Node::Fake); Node* n = findQmlClassNode(QStringList(name));
if (n) { if (n) {
if (n->subType() == Node::QmlClass) if (n->subType() == Node::QmlClass)
return static_cast<const QmlClassNode*>(n); return static_cast<QmlClassNode*>(n);
else if (n->subType() == Node::Collision) { else if (n->subType() == Node::Collision) {
const NameCollisionNode* ncn; NameCollisionNode* ncn;
ncn = static_cast<const NameCollisionNode*>(n); ncn = static_cast<NameCollisionNode*>(n);
return static_cast<const QmlClassNode*>(ncn->findAny(Node::Fake,Node::QmlClass)); return static_cast<QmlClassNode*>(ncn->findAny(Node::Fake,Node::QmlClass));
} }
} }
return 0; return 0;
@ -397,16 +346,15 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1) if (i == path.size() - 1)
next = ((InnerNode*) node)->findFunctionNode(path.at(i)); next = ((InnerNode*) node)->findFunctionNode(path.at(i));
else else
next = ((InnerNode*) node)->findNode(path.at(i)); next = ((InnerNode*) node)->findChildNodeByName(path.at(i));
if (!next && node->type() == Node::Class && if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
(findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node)); NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) { foreach (const Node* baseClass, baseClasses) {
if (i == path.size() - 1) if (i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i)); next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i));
else else
next = static_cast<const InnerNode*>(baseClass)->findNode(path.at(i)); next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
if (next) if (next)
break; break;
@ -474,6 +422,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
return ((InnerNode*)parent)->findFunctionNode(clone); return ((InnerNode*)parent)->findFunctionNode(clone);
} }
} }
//findNode(parameter.leftType().split("::"), 0, SearchBaseClasses|NonFunction);
static const int NumSuffixes = 3; static const int NumSuffixes = 3;
static const char* const suffixes[NumSuffixes] = { "", "s", "es" }; static const char* const suffixes[NumSuffixes] = { "", "s", "es" };
@ -768,17 +717,12 @@ void Tree::resolveInheritance(int pass, ClassNode* classe)
QList<InheritanceBound> bounds = priv->unresolvedInheritanceMap[classe]; QList<InheritanceBound> bounds = priv->unresolvedInheritanceMap[classe];
QList<InheritanceBound>::ConstIterator b = bounds.begin(); QList<InheritanceBound>::ConstIterator b = bounds.begin();
while (b != bounds.end()) { while (b != bounds.end()) {
ClassNode* baseClass = (ClassNode*)findNode((*b).basePath, Node* n = findClassNode((*b).basePath);
Node::Class); if (!n && (*b).parent) {
if (!baseClass && (*b).parent) { n = findClassNode((*b).basePath, (*b).parent);
baseClass = (ClassNode*)findNode((*b).basePath,
Node::Class,
(*b).parent);
} }
if (baseClass) { if (n) {
classe->addBaseClass((*b).access, classe->addBaseClass((*b).access, static_cast<ClassNode*>(n), (*b).dataTypeWithTemplateArgs);
baseClass,
(*b).dataTypeWithTemplateArgs);
} }
++b; ++b;
} }
@ -814,11 +758,9 @@ void Tree::resolveGroups()
if (i.value()->access() == Node::Private) if (i.value()->access() == Node::Private)
continue; continue;
FakeNode* fake = Node* n = findGroupNode(QStringList(i.key()));
static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake)); if (n)
if (fake && fake->subType() == Node::Group) { n->addGroupMember(i.value());
fake->addGroupMember(i.value());
}
} }
} }
@ -830,11 +772,9 @@ void Tree::resolveQmlModules()
{ {
NodeMultiMap::const_iterator i; NodeMultiMap::const_iterator i;
for (i = priv->qmlModuleMap.constBegin(); i != priv->qmlModuleMap.constEnd(); ++i) { for (i = priv->qmlModuleMap.constBegin(); i != priv->qmlModuleMap.constEnd(); ++i) {
FakeNode* fake = Node* n = findQmlModuleNode(QStringList(i.key()));
static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake)); if (n)
if (fake && fake->subType() == Node::QmlModule) { n->addQmlModuleMember(i.value());
fake->addQmlModuleMember(i.value());
}
} }
} }
@ -978,15 +918,13 @@ FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classe,
/*! /*!
*/ */
void Tree::fixPropertyUsingBaseClasses(ClassNode* classe, void Tree::fixPropertyUsingBaseClasses(ClassNode* classe, PropertyNode* property)
PropertyNode* property)
{ {
QList<RelatedClass>::const_iterator r = classe->baseClasses().begin(); QList<RelatedClass>::const_iterator r = classe->baseClasses().begin();
while (r != classe->baseClasses().end()) { while (r != classe->baseClasses().end()) {
PropertyNode* baseProperty = Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property);
static_cast<PropertyNode*>(r->node->findNode(property->name(), if (n) {
Node::Property)); PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
if (baseProperty) {
fixPropertyUsingBaseClasses(r->node, baseProperty); fixPropertyUsingBaseClasses(r->node, baseProperty);
property->setOverriddenFrom(baseProperty); property->setOverriddenFrom(baseProperty);
} }
@ -1414,10 +1352,9 @@ void Tree::resolveIndex()
foreach (pair, priv->basesList) { foreach (pair, priv->basesList) {
foreach (const QString& base, pair.second.split(QLatin1Char(','))) { foreach (const QString& base, pair.second.split(QLatin1Char(','))) {
Node* baseClass = root()->findNode(base, Node::Class); Node* n = root()->findChildNodeByNameAndType(base, Node::Class);
if (baseClass) { if (n) {
pair.first->addBaseClass(Node::Public, pair.first->addBaseClass(Node::Public, static_cast<ClassNode*>(n));
static_cast<ClassNode*>(baseClass));
} }
} }
} }
@ -1425,9 +1362,9 @@ void Tree::resolveIndex()
QPair<FunctionNode*,QString> relatedPair; QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, priv->relatedList) { foreach (relatedPair, priv->relatedList) {
Node* classNode = root()->findNode(relatedPair.second, Node::Class); Node* n = root()->findChildNodeByNameAndType(relatedPair.second, Node::Class);
if (classNode) if (n)
relatedPair.first->setRelates(static_cast<ClassNode*>(classNode)); relatedPair.first->setRelates(static_cast<ClassNode*>(n));
} }
} }
@ -1437,8 +1374,8 @@ void Tree::resolveIndex()
false. false.
*/ */
bool Tree::generateIndexSection(QXmlStreamWriter& writer, bool Tree::generateIndexSection(QXmlStreamWriter& writer,
const Node* node, Node* node,
bool generateInternalNodes) const bool generateInternalNodes)
{ {
if (!node->url().isEmpty()) if (!node->url().isEmpty())
return false; return false;
@ -1473,9 +1410,6 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
case Node::Variable: case Node::Variable:
nodeName = "variable"; nodeName = "variable";
break; break;
case Node::Target:
nodeName = "target";
break;
case Node::QmlProperty: case Node::QmlProperty:
nodeName = "qmlproperty"; nodeName = "qmlproperty";
break; break;
@ -1716,7 +1650,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
case Node::QmlProperty: case Node::QmlProperty:
{ {
const QmlPropertyNode* qpn = static_cast<const QmlPropertyNode*>(node); QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
writer.writeAttribute("type", qpn->dataType()); writer.writeAttribute("type", qpn->dataType());
writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false"); writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false");
writer.writeAttribute("writable", qpn->isWritable(this) ? "true" : "false"); writer.writeAttribute("writable", qpn->isWritable(this) ? "true" : "false");
@ -1840,22 +1774,18 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
foreach (const Parameter& parameter, functionNode->parameters()) { foreach (const Parameter& parameter, functionNode->parameters()) {
QString leftType = parameter.leftType(); QString leftType = parameter.leftType();
const Node* leftNode = const Node* leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"), 0, SearchBaseClasses|NonFunction);
Node::Typedef, 0, SearchBaseClasses|NonFunction); if (!leftNode || leftNode->type() != Node::Typedef) {
if (!leftNode) { leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
leftNode = const_cast<Tree*>(this)->findNode(
parameter.leftType().split("::"), Node::Typedef,
node->parent(), SearchBaseClasses|NonFunction); node->parent(), SearchBaseClasses|NonFunction);
} }
if (leftNode) { if (leftNode && leftNode->type() == Node::Typedef) {
if (leftNode->type() == Node::Typedef) { if (leftNode->type() == Node::Typedef) {
const TypedefNode* typedefNode = const TypedefNode* typedefNode =
static_cast<const TypedefNode*>(leftNode); static_cast<const TypedefNode*>(leftNode);
if (typedefNode->associatedEnum()) { if (typedefNode->associatedEnum()) {
leftType = "QFlags<" + leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>');
typedefNode->associatedEnum()->fullDocumentName() +
QLatin1Char('>');
} }
} }
else else
@ -1973,8 +1903,8 @@ bool compareNodes(const Node* n1, const Node* n2)
they will be omitted. they will be omitted.
*/ */
void Tree::generateIndexSections(QXmlStreamWriter& writer, void Tree::generateIndexSections(QXmlStreamWriter& writer,
const Node* node, Node* node,
bool generateInternalNodes) const bool generateInternalNodes)
{ {
if (generateIndexSection(writer, node, generateInternalNodes)) { if (generateIndexSection(writer, node, generateInternalNodes)) {
@ -1984,7 +1914,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer,
NodeList cnodes = inner->childNodes(); NodeList cnodes = inner->childNodes();
qSort(cnodes.begin(), cnodes.end(), compareNodes); qSort(cnodes.begin(), cnodes.end(), compareNodes);
foreach (const Node* child, cnodes) { foreach (Node* child, cnodes) {
/* /*
Don't generate anything for a QML property group node. Don't generate anything for a QML property group node.
It is just a place holder for a collection of QML property It is just a place holder for a collection of QML property
@ -1993,7 +1923,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer,
*/ */
if (child->subType() == Node::QmlPropertyGroup) { if (child->subType() == Node::QmlPropertyGroup) {
const InnerNode* pgn = static_cast<const InnerNode*>(child); const InnerNode* pgn = static_cast<const InnerNode*>(child);
foreach (const Node* c, pgn->childNodes()) { foreach (Node* c, pgn->childNodes()) {
generateIndexSections(writer, c, generateInternalNodes); generateIndexSections(writer, c, generateInternalNodes);
} }
} }
@ -2018,7 +1948,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer,
void Tree::generateIndex(const QString& fileName, void Tree::generateIndex(const QString& fileName,
const QString& url, const QString& url,
const QString& title, const QString& title,
bool generateInternalNodes) const bool generateInternalNodes)
{ {
QFile file(fileName); QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) if (!file.open(QFile::WriteOnly | QFile::Text))
@ -2047,8 +1977,7 @@ void Tree::generateIndex(const QString& fileName,
specified, returning true if an element was written; otherwise returns specified, returning true if an element was written; otherwise returns
false. false.
*/ */
void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, const InnerNode* inner)
const InnerNode* inner) const
{ {
foreach (const Node* node, inner->childNodes()) { foreach (const Node* node, inner->childNodes()) {
@ -2068,7 +1997,6 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer,
case Node::Property: case Node::Property:
case Node::Function: case Node::Function:
case Node::Variable: case Node::Variable:
case Node::Target:
default: default:
continue; continue;
} }
@ -2130,8 +2058,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer,
/*! /*!
*/ */
void Tree::generateTagFileMembers(QXmlStreamWriter& writer, void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inner)
const InnerNode* inner) const
{ {
foreach (const Node* node, inner->childNodes()) { foreach (const Node* node, inner->childNodes()) {
@ -2164,7 +2091,6 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer,
nodeName = "class"; nodeName = "class";
break; break;
case Node::Variable: case Node::Variable:
case Node::Target:
default: default:
continue; continue;
} }
@ -2247,18 +2173,15 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer,
foreach (const Parameter& parameter, functionNode->parameters()) { foreach (const Parameter& parameter, functionNode->parameters()) {
QString leftType = parameter.leftType(); QString leftType = parameter.leftType();
const Node* leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"), const Node* leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
Node::Typedef, 0, SearchBaseClasses|NonFunction); 0, SearchBaseClasses|NonFunction);
if (!leftNode) { if (!leftNode || leftNode->type() != Node::Typedef) {
leftNode = const_cast<Tree*>(this)->findNode( leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
parameter.leftType().split("::"), Node::Typedef, node->parent(), SearchBaseClasses|NonFunction);
node->parent(), SearchBaseClasses|NonFunction);
} }
if (leftNode) { if (leftNode && leftNode->type() == Node::Typedef) {
const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode); const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
if (typedefNode->associatedEnum()) { if (typedefNode->associatedEnum()) {
leftType = "QFlags<" + leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>');
typedefNode->associatedEnum()->fullDocumentName() +
QLatin1Char('>');
} }
} }
signatureList.append(leftType + QLatin1Char(' ') + parameter.name()); signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
@ -2324,7 +2247,6 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer,
break; break;
case Node::Variable: case Node::Variable:
case Node::Target:
default: default:
break; break;
} }
@ -2332,8 +2254,9 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer,
} }
/*! /*!
Writes a tag file named \a fileName.
*/ */
void Tree::generateTagFile(const QString& fileName) const void Tree::generateTagFile(const QString& fileName)
{ {
QFile file(fileName); QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) if (!file.open(QFile::WriteOnly | QFile::Text))
@ -2366,4 +2289,239 @@ void Tree::addExternalLink(const QString& url, const Node* relative)
fakeNode->setDoc(doc); fakeNode->setDoc(doc);
} }
/*!
Find the node with the specified \a path name that is of
the specified \a type and \a subtype. Begin the search at
the \a start node. If the \a start node is 0, begin the
search at the tree root. \a subtype is not used unless
\a type is \c{Fake}.
*/
Node* Tree::findNodeByNameAndType(const QStringList& path,
Node::Type type,
Node::SubType subtype,
Node* start,
bool acceptCollision)
{
if (!start)
start = const_cast<NamespaceNode*>(root());
Node* result = findNodeRecursive(path, 0, start, type, subtype, acceptCollision);
return result;
}
#if 0
if (result)
qDebug() << "FOUND:" << path << Node::nodeTypeString(type)
<< Node::nodeSubtypeString(subtype);
else
qDebug() << "NOT FOUND:" << path << Node::nodeTypeString(type)
<< Node::nodeSubtypeString(subtype);
#endif
/*!
Recursive search for a node identified by \a path. Each
path element is a name. \a pathIndex specifies the index
of the name in \a path to try to match. \a start is the
node whose children shoulod be searched for one that has
that name. Each time a match is found, increment the
\a pathIndex and call this function recursively.
If the end of the path is reached (i.e. if a matching
node is found for each name in the \a path), the \a type
must match the type of the last matching node, and if the
type is \e{Fake}, the \a subtype must match as well.
If the algorithm is successful, the pointer to the final
node is returned. Otherwise 0 is returned.
*/
Node* Tree::findNodeRecursive(const QStringList& path,
int pathIndex,
Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision)
{
if (!start || path.isEmpty())
return 0; // no place to start, or nothing to search for.
if (start->isLeaf()) {
if (pathIndex >= path.size())
return start; // found a match.
return 0; // premature leaf
}
if (pathIndex >= path.size())
return 0; // end of search path.
InnerNode* current = static_cast<InnerNode*>(start);
const NodeList& children = current->childNodes();
const QString& name = path.at(pathIndex);
for (int i=0; i<children.size(); ++i) {
Node* n = children.at(i);
if (!n)
continue;
if (n->isQmlPropertyGroup()) {
if (type == Node::QmlProperty) {
n = findNodeRecursive(path, pathIndex, n, type, subtype);
if (n)
return n;
}
}
else if (n->name() == name) {
if (pathIndex+1 >= path.size()) {
if (n->type() == type) {
if (type == Node::Fake) {
if (n->subType() == subtype)
return n;
else if (n->subType() == Node::Collision && acceptCollision)
return n;
else if (subtype == Node::NoSubType)
return n; // don't care what subtype is.
return 0;
}
else
return n;
}
else if (n->isCollisionNode()) {
if (acceptCollision)
return n;
return n = findNodeRecursive(path, pathIndex, n, type, subtype);
if (n)
return n;
}
else
return 0;
}
else { // Not at the end of the path.
n = findNodeRecursive(path, pathIndex+1, n, type, subtype);
if (n)
return n;
}
}
}
return 0;
}
/*!
Find the Enum type node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only an Enum type node named \a path is
acceptible. If one is not found, 0 is returned.
*/
EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
{
return static_cast<EnumNode*>(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType));
}
/*!
Find the C++ class node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a C++ class node named \a path is
acceptible. If one is not found, 0 is returned.
*/
ClassNode* Tree::findClassNode(const QStringList& path, Node* start)
{
return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
}
/*!
Find the Qml class node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Qml class node named \a path is
acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlClassNode(const QStringList& path, Node* start)
{
/*
If the path contains one or two double colons ("::"),
check first to see if the first two path strings refer
to a QML element. If yes, that reference identifies a
QML class node.
*/
if (path.size() >= 2) {
QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]);
if (qcn)
return qcn;
}
return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, start, Node::Fake, Node::QmlClass));
}
/*!
Find the Namespace node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Namespace node named \a path is
acceptible. If one is not found, 0 is returned.
*/
NamespaceNode* Tree::findNamespaceNode(const QStringList& path, Node* start)
{
return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
}
/*!
Find the Group node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Group node named \a path is
acceptible. If one is not found, 0 is returned.
*/
FakeNode* Tree::findGroupNode(const QStringList& path, Node* start)
{
return static_cast<FakeNode*>(findNodeRecursive(path, 0, start, Node::Fake, Node::Group));
}
/*!
Find the Qml module node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Qml module node named \a path is
acceptible. If one is not found, 0 is returned.
*/
FakeNode* Tree::findQmlModuleNode(const QStringList& path, Node* start)
{
return static_cast<FakeNode*>(findNodeRecursive(path, 0, start, Node::Fake, Node::QmlModule));
}
QT_END_NAMESPACE QT_END_NAMESPACE
#if 0
const Node* Tree::findNodeXXX(const QStringList& path, bool qml) const
{
const Node* current = root();
do {
const Node* node = current;
int i;
int start_idx = 0;
/*
If the path contains one or two double colons ("::"),
check first to see if the first two path strings refer
to a QML element. If yes, that reference identifies a
QML class node.
*/
if (qml && path.size() >= 2) {
QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]);
if (qcn) {
node = qcn;
if (path.size() == 2)
return node;
start_idx = 2;
}
}
for (i = start_idx; i < path.size(); ++i) {
if (node == 0 || !node->isInnerNode())
break;
const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
node = next;
}
if (node && i == path.size()) {
if (node->subType() != Node::QmlPropertyGroup) {
if (node->subType() == Node::Collision) {
node = node->applyModuleIdentifier(start);
}
return node;
}
}
current = current->parent();
} while (current);
return 0;
}
#endif

View File

@ -65,19 +65,39 @@ public:
Tree(); Tree();
~Tree(); ~Tree();
Node* findNode(const QStringList &path, EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
Node* relative=0, ClassNode* findClassNode(const QStringList& path, Node* start = 0);
int findFlags=0, QmlClassNode* findQmlClassNode(const QStringList& path, Node* start = 0);
const Node* self=0); NamespaceNode* findNamespaceNode(const QStringList& path, Node* start = 0);
Node* findNode(const QStringList &path, FakeNode* findGroupNode(const QStringList& path, Node* start = 0);
Node::Type type, FakeNode* findQmlModuleNode(const QStringList& path, Node* start = 0);
Node* relative = 0,
int findFlags = 0); Node* findNodeByNameAndType(const QStringList& path,
Node::Type type,
Node::SubType subtype,
Node* start,
bool acceptCollision = false);
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision = false);
const Node* findNode(const QStringList &path,
const Node* relative = 0,
int findFlags = 0,
const Node* self=0) const;
private:
const Node* findNode(const QStringList& path, const Node* findNode(const QStringList& path,
const Node* start, const Node* start,
int findFlags, int findFlags,
const Node* self, const Node* self,
bool qml) const; bool qml) const;
public:
QmlClassNode* findQmlClassNode(const QString& module, const QString& name); QmlClassNode* findQmlClassNode(const QString& module, const QString& name);
NameCollisionNode* checkForCollision(const QString& name) const; NameCollisionNode* checkForCollision(const QString& name) const;
NameCollisionNode* findCollisionNode(const QString& name) const; NameCollisionNode* findCollisionNode(const QString& name) const;
@ -111,17 +131,8 @@ public:
void fixInheritance(NamespaceNode *rootNode = 0); void fixInheritance(NamespaceNode *rootNode = 0);
void setVersion(const QString &version) { vers = version; } void setVersion(const QString &version) { vers = version; }
NamespaceNode *root() { return &roo; } NamespaceNode *root() { return &roo; }
QString version() const { return vers; } QString version() const { return vers; }
const Node* findNode(const QStringList &path,
const Node* relative = 0,
int findFlags = 0,
const Node* self=0) const;
const Node* findNode(const QStringList &path,
Node::Type type, const
Node* relative = 0,
int findFlags = 0) const;
const QmlClassNode* findQmlClassNode(const QString& module, const QString& element) const;
const FunctionNode *findFunctionNode(const QStringList &path, const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0, const Node *relative = 0,
int findFlags = 0) const; int findFlags = 0) const;
@ -134,19 +145,17 @@ public:
Atom *findTarget(const QString &target, const Node *node) const; Atom *findTarget(const QString &target, const Node *node) const;
const NamespaceNode *root() const { return &roo; } const NamespaceNode *root() const { return &roo; }
void readIndexes(const QStringList &indexFiles); void readIndexes(const QStringList &indexFiles);
bool generateIndexSection(QXmlStreamWriter &writer, const Node *node, bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
bool generateInternalNodes = false) const; void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter &writer, const Node *node,
bool generateInternalNodes = false) const;
void generateIndex(const QString &fileName, void generateIndex(const QString &fileName,
const QString &url, const QString &url,
const QString &title, const QString &title,
bool generateInternalNodes = false) const; bool generateInternalNodes = false);
void generateTagFileCompounds(QXmlStreamWriter &writer, void generateTagFileCompounds(QXmlStreamWriter &writer,
const InnerNode *inner) const; const InnerNode *inner);
void generateTagFileMembers(QXmlStreamWriter &writer, void generateTagFileMembers(QXmlStreamWriter &writer,
const InnerNode *inner) const; const InnerNode *inner);
void generateTagFile(const QString &fileName) const; void generateTagFile(const QString &fileName);
void addExternalLink(const QString &url, const Node *relative); void addExternalLink(const QString &url, const Node *relative);
QString fullDocumentLocation(const Node *node) const; QString fullDocumentLocation(const Node *node) const;
void resolveQmlInheritance(); void resolveQmlInheritance();