qdoc: Write all generated files to .qhp

When writing the Qt Help Project XML file, QDoc traverses the
documentation nodes recursively, adding html filenames for each node
to the XML.

The logic that QDoc uses for this process is not perfect, and needs
to be kept up to date whenever the internal structure of the node
tree changes. This often leads to problems where some pages are
generated but not added to the .qhp, resulting in missing pages in
the offline documentation.

This change fixes this problem by having the generator keep track
of the created filenames, and passing that to the help project
writer.

Task-number: QTBUG-40572
Change-Id: Ife60a30724183a2b6dcd2397ea79bfbdc2addd04
Reviewed-by: Martin Smith <martin.smith@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Topi Reinio 2014-08-04 14:35:05 +02:00 committed by Topi Reiniö
parent 4f2d1e2e04
commit 4cc3a41819
4 changed files with 19 additions and 41 deletions

View File

@ -69,6 +69,7 @@ QStringList Generator::imageFiles;
QMap<QString, QStringList> Generator::imgFileExts;
QString Generator::outDir_;
QString Generator::outSubdir_;
QStringList Generator::outFileNames_;
QSet<QString> Generator::outputFormats;
QHash<QString, QString> Generator::outputPrefixes;
QString Generator::project;
@ -244,8 +245,6 @@ void Generator::appendSortedQmlNames(Text& text, const Node* base, const NodeLis
}
}
QMultiMap<QString,QString> outFileNames;
/*!
For debugging qdoc.
*/
@ -255,10 +254,8 @@ void Generator::writeOutFileNames()
if (!files.open(QFile::WriteOnly))
return;
QTextStream filesout(&files);
QMultiMap<QString,QString>::ConstIterator i = outFileNames.begin();
while (i != outFileNames.end()) {
filesout << i.key() << "\n";
++i;
foreach (const QString &file, outFileNames_) {
filesout << file << "\n";
}
}
@ -280,7 +277,7 @@ void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
if (!outFile->open(QFile::WriteOnly))
node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
Generator::debug("Writing: " + path);
outFileNames.insert(fileName,fileName);
outFileNames_ << fileName;
QTextStream* out = new QTextStream(outFile);
#ifndef QT_NO_TEXTCODEC

View File

@ -90,6 +90,7 @@ public:
static const QString& outputDir() { return outDir_; }
static const QString& outputSubdir() { return outSubdir_; }
static void terminate();
static const QStringList& outputFileNames() { return outFileNames_; }
static void writeOutFileNames();
static void augmentImageDirs(QSet<QString>& moreImageDirs);
static void debug(const QString& message);
@ -208,6 +209,7 @@ private:
static QString project;
static QString outDir_;
static QString outSubdir_;
static QStringList outFileNames_;
static QSet<QString> outputFormats;
static QHash<QString, QString> outputPrefixes;
static QStringList scriptDirs;

View File

@ -284,7 +284,6 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
case Node::Class:
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
case Node::QmlType:
case Node::QmlBasicType:
@ -303,12 +302,10 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
}
}
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
case Node::Namespace:
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
case Node::Enum:
@ -357,7 +354,6 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
}
}
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
}
}
break;
@ -388,7 +384,6 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
if (node->relates()) {
project.memberStatus[node->relates()].insert(node->status());
project.files.insert(gen_->fullDocumentLocation(node->relates(),Generator::useOutputSubdirs()));
} else if (node->parent())
project.memberStatus[node->parent()].insert(node->status());
}
@ -410,8 +405,6 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
case Node::Variable:
{
QString location = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
project.files.insert(location.left(location.lastIndexOf(QLatin1Char('#'))));
project.keywords.append(keywordDetails(node));
}
break;
@ -442,7 +435,6 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
}
project.keywords.append(keywordDetails(node));
}
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
}
break;
}
@ -513,8 +505,6 @@ void HelpProjectWriter::generateSections(HelpProject &project,
project.memberStatus[node].insert(childNode->status());
if (childNode->relates()) {
project.memberStatus[childNode->relates()].insert(childNode->status());
project.files.insert(gen_->fullDocumentLocation(childNode->relates(),
Generator::useOutputSubdirs()));
}
if (childNode->type() == Node::Function) {
@ -525,11 +515,6 @@ void HelpProjectWriter::generateSections(HelpProject &project,
childMap[childNode->fullDocumentName()] = childNode;
}
}
// Insert files for all/compatibility/obsolete members
addMembers(project, writer, node, false);
if (node->relates())
addMembers(project, writer, node->relates(), false);
foreach (const Node *child, childMap)
generateSections(project, writer, child);
}
@ -564,11 +549,10 @@ void HelpProjectWriter::writeSection(QXmlStreamWriter &writer, const QString &pa
}
/*
Add files for all members, compatibility members and obsolete members
Also write subsections for these depending on 'writeSections' (default=true).
Write subsections for all members, compatibility members and obsolete members.
*/
void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &writer,
const Node *node, bool writeSections)
const Node *node)
{
QString href = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
href = href.left(href.size()-5);
@ -584,21 +568,15 @@ void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &write
if (!node->isNamespace() && !node->isHeaderFile() &&
(derivedClass || node->isQmlType() || !project.memberStatus[node].isEmpty())) {
QString membersPath = href + QStringLiteral("-members.html");
project.files.insert(membersPath);
if (writeSections)
writeSection(writer, membersPath, tr("List of all members"));
writeSection(writer, membersPath, tr("List of all members"));
}
if (project.memberStatus[node].contains(Node::Compat)) {
QString compatPath = href + QStringLiteral("-compat.html");
project.files.insert(compatPath);
if (writeSections)
writeSection(writer, compatPath, tr("Compatibility members"));
writeSection(writer, compatPath, tr("Compatibility members"));
}
if (project.memberStatus[node].contains(Node::Obsolete)) {
QString obsoletePath = href + QStringLiteral("-obsolete.html");
project.files.insert(obsoletePath);
if (writeSections)
writeSection(writer, obsoletePath, tr("Obsolete members"));
writeSection(writer, obsoletePath, tr("Obsolete members"));
}
}
@ -722,7 +700,6 @@ void HelpProjectWriter::generateProject(HelpProject &project)
indexPath = "index.html";
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", project.indexTitle);
project.files.insert(gen_->fullDocumentLocation(rootNode));
generateSections(project, writer, rootNode);
@ -764,7 +741,6 @@ void HelpProjectWriter::generateProject(HelpProject &project)
Generator::useOutputSubdirs());
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", atom->string());
project.files.insert(indexPath);
sectionStack.top() += 1;
}
@ -789,7 +765,6 @@ void HelpProjectWriter::generateProject(HelpProject &project)
QString indexPath = gen_->fullDocumentLocation(qdb_->findDocNodeByTitle(subproject.indexTitle),Generator::useOutputSubdirs());
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", subproject.title);
project.files.insert(indexPath);
}
if (subproject.sortPages) {
QStringList titles = subproject.nodes.keys();
@ -843,12 +818,16 @@ void HelpProjectWriter::generateProject(HelpProject &project)
writer.writeEndElement(); // keywords
writer.writeStartElement("files");
foreach (const QString &usedFile, project.files) {
// The list of files to write is the union of generated files and
// other files (images and extras) included in the project
QSet<QString> files = QSet<QString>::fromList(gen_->outputFileNames());
files.unite(project.files);
files.unite(project.extraFiles);
foreach (const QString &usedFile, files) {
if (!usedFile.isEmpty())
writer.writeTextElement("file", usedFile);
}
foreach (const QString &usedFile, project.extraFiles)
writer.writeTextElement("file", usedFile);
writer.writeEndElement(); // files
writer.writeEndElement(); // filterSection

View File

@ -106,7 +106,7 @@ private:
void writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node);
void readSelectors(SubProject &subproject, const QStringList &selectors);
void addMembers(HelpProject &project, QXmlStreamWriter &writer,
const Node *node, bool writeSections = true);
const Node *node);
void writeSection(QXmlStreamWriter &writer, const QString &path,
const QString &value);