qdoc: List of all members subpage redesigned

The subpage listing all the members of a QML type,
including the inherited members, was trying to use
an old format that works ok for C++ classes but is
not optimal for QML types.

The redesigned format for QML types still lists all
the members but it lists the members for each base
type in a separate list.

The members for a QML type that has been marked as
abstract are listed with the members of the type
that inherits the abstract type.

This fix does not fix QTBUG-30111, which will be
fixed in a separate commit. This means that some
links on the subpage generated by this change
will be links to a page that doesn't actually
contain any documentation for the linked member.
But it will eventually.

Task-number: QTBUG-30114
Change-Id: I8ae4227d1eaecdbc24a4ac9b8119f0ced2cdee92
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Martin Smith 2013-03-20 13:26:09 +01:00 committed by The Qt Project
parent bf3a5ccef1
commit 04770e5824
4 changed files with 124 additions and 22 deletions

View File

@ -381,8 +381,9 @@ QString CodeMarker::sortName(const Node *node, const QString* name)
if ((node->type() == Node::QmlMethod) ||
(node->type() == Node::QmlSignal) ||
(node->type() == Node::QmlSignalHandler)) {
const FunctionNode* func = static_cast<const FunctionNode *>(node);
return QLatin1Char('E') + func->name();
//const FunctionNode* func = static_cast<const FunctionNode *>(node);
//return QLatin1Char('E') + func->name();
return QLatin1Char('E') + nodeName;
}
return QLatin1Char('B') + nodeName;
@ -518,14 +519,59 @@ bool CodeMarker::insertReimpFunc(FastSection& fs, Node* node, Status status)
void CodeMarker::append(QList<Section>& sectionList, const FastSection& fs, bool includeKeys)
{
if (!fs.isEmpty()) {
Section section(fs.name,fs.divClass,fs.singularMember,fs.pluralMember);
if (includeKeys) {
section.keys = fs.memberMap.keys();
if (fs.classMapList_.isEmpty()) {
Section section(fs.name,fs.divClass,fs.singularMember,fs.pluralMember);
if (includeKeys) {
section.keys = fs.memberMap.keys();
}
section.members = fs.memberMap.values();
section.reimpMembers = fs.reimpMemberMap.values();
section.inherited = fs.inherited;
sectionList.append(section);
}
else {
Section section(fs.name,fs.divClass,fs.singularMember,fs.pluralMember);
sectionList.append(section);
Section* s = &sectionList[sectionList.size()-1];
for (int i=0; i<fs.classMapList_.size(); i++) {
ClassMap* classMap = fs.classMapList_[i];
ClassKeysNodes* ckn = new ClassKeysNodes;
ckn->first = classMap->first;
ckn->second.second = classMap->second.values();
ckn->second.first = classMap->second.keys();
s->classKeysNodesList_.append(ckn);
}
}
}
}
/*!
The destructor must delete each member of the
list of QML class lists, if it is not empty;
*/
Section::~Section()
{
if (!classKeysNodesList_.isEmpty()) {
for (int i=0; i<classKeysNodesList_.size(); i++) {
ClassKeysNodes* classKeysNodes = classKeysNodesList_[i];
classKeysNodesList_[i] = 0;
delete classKeysNodes;
}
}
}
/*!
The destructor must delete the QML class maps in the class
map list, if the class map list is not empty.
*/
FastSection::~FastSection()
{
if (!classMapList_.isEmpty()) {
for (int i=0; i<classMapList_.size(); i++) {
ClassMap* classMap = classMapList_[i];
classMapList_[i] = 0;
delete classMap;
}
section.members = fs.memberMap.values();
section.reimpMembers = fs.reimpMemberMap.values();
section.inherited = fs.inherited;
sectionList.append(section);
}
}

View File

@ -56,6 +56,14 @@ QT_BEGIN_NAMESPACE
class Config;
class Tree;
typedef QMultiMap<QString, Node*> MemberMap; // the string is the member signature
typedef QPair<const QmlClassNode*, MemberMap> ClassMap; // the node is the QML type
typedef QList<ClassMap*> ClassMapList;
typedef QPair<QStringList, NodeList> KeysAndNodes;
typedef QPair<const QmlClassNode*, KeysAndNodes> ClassKeysNodes;
typedef QList<ClassKeysNodes*> ClassKeysNodesList;
struct Section
{
QString name;
@ -66,6 +74,7 @@ struct Section
NodeList members;
NodeList reimpMembers;
QList<QPair<InnerNode *, int> > inherited;
ClassKeysNodesList classKeysNodesList_;
Section() { }
Section(const QString& name0,
@ -76,6 +85,7 @@ struct Section
divClass(divClass0),
singularMember(singularMember0),
pluralMember(pluralMember0) { }
~Section();
void appendMember(Node* node) { members.append(node); }
void appendReimpMember(Node* node) { reimpMembers.append(node); }
};
@ -87,8 +97,9 @@ struct FastSection
QString divClass;
QString singularMember;
QString pluralMember;
QMap<QString, Node *> memberMap;
QMap<QString, Node *> reimpMemberMap;
QMultiMap<QString, Node *> memberMap;
QMultiMap<QString, Node *> reimpMemberMap;
ClassMapList classMapList_;
QList<QPair<InnerNode *, int> > inherited;
FastSection(const InnerNode *parent,
@ -101,10 +112,12 @@ struct FastSection
divClass(divClass0),
singularMember(singularMember0),
pluralMember(pluralMember0) { }
~FastSection();
bool isEmpty() const {
return (memberMap.isEmpty() &&
inherited.isEmpty() &&
reimpMemberMap.isEmpty());
reimpMemberMap.isEmpty() &&
classMapList_.isEmpty());
}
};

View File

@ -1258,9 +1258,24 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
append(sections,qmlattachedmethods);
}
else {
/*
This is where the list of all members including inherited
members is prepared.
*/
ClassMap* classMap = 0;
FastSection all(qmlClassNode,QString(),QString(),"member","members");
const QmlClassNode* current = qmlClassNode;
while (current != 0) {
/*
If the QML type is abstract, do not create
a new entry in the list for it. Instead,
add its members to the current entry.
*/
if (!current->isAbstract()) {
classMap = new ClassMap;
classMap->first = current;
all.classMapList_.append(classMap);
}
NodeList::ConstIterator c = current->childNodes().constBegin();
while (c != current->childNodes().constEnd()) {
if ((*c)->subType() == Node::QmlPropertyGroup) {
@ -1268,21 +1283,19 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
QString key = current->name() + "::" + (*p)->name();
QString key = (*p)->name();
key = sortName(*p, &key);
if (!all.memberMap.contains(key)) {
all.memberMap.insert(key,*p);
}
all.memberMap.insert(key,*p);
classMap->second.insert(key,*p);
}
++p;
}
}
else {
QString key = current->name() + "::" + (*c)->name();
QString key = (*c)->name();
key = sortName(*c, &key);
if (!all.memberMap.contains(key)) {
all.memberMap.insert(key,*c);
}
all.memberMap.insert(key,*c);
classMap->second.insert(key,*c);
}
++c;
}

View File

@ -2067,8 +2067,38 @@ QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn,
generateFullName(qml_cn, 0);
out() << ", including inherited members.</p>\n";
Section section = sections.first();
generateSectionList(section, 0, marker, CodeMarker::Subpage);
ClassKeysNodesList& cknl = sections.first().classKeysNodesList_;
if (!cknl.isEmpty()) {
for (int i=0; i<cknl.size(); i++) {
ClassKeysNodes* ckn = cknl[i];
const QmlClassNode* qcn = ckn->first;
KeysAndNodes& kn = ckn->second;
QStringList& keys = kn.first;
NodeList& nodes = kn.second;
if (nodes.isEmpty())
continue;
if (i != 0) {
out() << "<p>The following members are inherited from ";
generateFullName(qcn,0);
out() << ".</p>\n";
}
out() << "<ul>\n";
for (int j=0; j<keys.size(); j++) {
if (nodes[j]->access() == Node::Private) {
continue;
}
out() << "<li class=\"fn\">";
QString prefix;
if (!keys.isEmpty()) {
prefix = keys.at(j).mid(1);
prefix = prefix.left(keys.at(j).indexOf("::")+1);
}
generateSynopsis(nodes[j], qcn, marker, CodeMarker::Summary, false, &prefix);
out() << "</li>\n";
}
out() << "</ul>\n";
}
}
generateFooter();
endSubPage();