qdoc: Restore support for output in one directory

The basic functionality is working. Add these lines
to qt-html-templates-offline.qdocconf, or add them
to the online version:

HTML.nosubdirs            = "true"
HTML.outputsubdir         = "html"

Before it opens a .html file for writing, it tests
whether the file alread exists. If so, it writes an
error message, e.g.:

...platform-notes.qdoc:140: error: HTML file already exists;
overwriting .../doc/html/platform-notes-windows.html

There are currently nearly 100 files being overwritten for Qt5.

Task-number: QTBUG-32580
Change-Id: I02b103fd00b9d1e624665ac518d571acc791be9d
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Martin Smith 2013-08-07 11:40:27 +02:00 committed by The Qt Project
parent 097942d328
commit bc87acaa1f
10 changed files with 78 additions and 41 deletions

View File

@ -279,10 +279,16 @@ int Config::getInt(const QString& var) const
*/
QString Config::getOutputDir() const
{
QString t;
if (overrideOutputDir.isNull())
return getString(QLatin1String(CONFIG_OUTPUTDIR));
t = getString(QLatin1String(CONFIG_OUTPUTDIR));
else
return overrideOutputDir;
t = overrideOutputDir;
if (!Generator::useOutputSubdirs()) {
t = t.left(t.lastIndexOf('/'));
t += QLatin1Char('/') + getString("HTML.outputsubdir");
}
return t;
}
/*!

View File

@ -3758,7 +3758,7 @@ QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
back down into the other subdirectory.
*/
if (node && relative && (node != relative)) {
if (node->outputSubdirectory() != relative->outputSubdirectory())
if (useOutputSubdirs() && node->outputSubdirectory() != relative->outputSubdirectory())
link.prepend(QString("../" + node->outputSubdirectory() + QLatin1Char('/')));
}
return link;

View File

@ -99,6 +99,7 @@ bool Generator::debugging_ = false;
bool Generator::noLinkErrors_ = false;
bool Generator::redirectDocumentationToDevNull_ = false;
Generator::Passes Generator::qdocPass_ = Both;
bool Generator::useOutputSubdirs_ = true;
void Generator::setDebugSegfaultFlag(bool b)
{
@ -264,15 +265,17 @@ void Generator::writeOutFileNames()
void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
{
QString path = outputDir() + QLatin1Char('/');
if (!node->outputSubdirectory().isEmpty())
if (Generator::useOutputSubdirs() && !node->outputSubdirectory().isEmpty())
path += node->outputSubdirectory() + QLatin1Char('/');
path += fileName;
Generator::debugSegfault("Writing: " + path);
outFileNames.insert(fileName,fileName);
QFile* outFile = new QFile(redirectDocumentationToDevNull_ ? QStringLiteral("/dev/null") : path);
if (outFile->exists())
node->location().error(tr("HTML file already exists; overwriting %1").arg(outFile->fileName()));
if (!outFile->open(QFile::WriteOnly))
node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
Generator::debugSegfault("Writing: " + path);
outFileNames.insert(fileName,fileName);
QTextStream* out = new QTextStream(outFile);
#ifndef QT_NO_TEXTCODEC
@ -419,7 +422,7 @@ QMap<QString, QString>& Generator::formattingRightMap()
/*!
Returns the full document location.
*/
QString Generator::fullDocumentLocation(const Node *node, bool subdir)
QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
{
if (!node)
return QString();
@ -431,11 +434,11 @@ QString Generator::fullDocumentLocation(const Node *node, bool subdir)
QString fdl;
/*
If the output is being sent to subdirectories of the
output directory, and if the subdir parameter is set,
prepend the subdirectory name + '/' to the result.
If the useSubdir parameter is set, then the output is
being sent to subdirectories of the output directory.
Prepend the subdirectory name + '/' to the result.
*/
if (subdir) {
if (useSubdir) {
fdl = node->outputSubdirectory();
if (!fdl.isEmpty())
fdl.append(QLatin1Char('/'));
@ -1491,6 +1494,10 @@ QString Generator::indent(int level, const QString& markedCode)
void Generator::initialize(const Config &config)
{
if (config.getBool(QString("HTML.nosubdirs")))
resetUseOutputSubdirs();
outputFormats = config.getOutputFormats();
redirectDocumentationToDevNull_ = config.getBool(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL);
if (!outputFormats.isEmpty()) {
@ -1505,7 +1512,7 @@ void Generator::initialize(const Config &config)
QDir dirInfo;
if (dirInfo.exists(outDir_)) {
if (!runGenerateOnly()) {
if (!runGenerateOnly() && Generator::useOutputSubdirs()) {
if (!Config::removeDirContents(outDir_))
config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
}

View File

@ -81,7 +81,7 @@ public:
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
QString fullDocumentLocation(const Node *node, bool subdir = false);
QString fullDocumentLocation(const Node *node, bool useSubdir = false);
const Config* config() { return config_; }
static Generator *currentGenerator() { return currentGenerator_; }
@ -100,6 +100,8 @@ public:
static bool runPrepareOnly() { return (qdocPass_ == Prepare); }
static bool runGenerateOnly() { return (qdocPass_ == Generate); }
static QString defaultModuleName() { return project; }
static void resetUseOutputSubdirs() { useOutputSubdirs_ = false; }
static bool useOutputSubdirs() { return useOutputSubdirs_; }
protected:
virtual void beginSubPage(const InnerNode* node, const QString& fileName);
@ -219,6 +221,7 @@ private:
static bool noLinkErrors_;
static bool redirectDocumentationToDevNull_;
static Passes qdocPass_;
static bool useOutputSubdirs_;
void generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker);

View File

@ -225,7 +225,7 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const
details << node->name();
details << node->name();
}
details << gen_->fullDocumentLocation(node,true);
details << gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
return details;
}
@ -285,12 +285,12 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
case Node::Class:
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,true));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
case Node::Namespace:
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,true));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
break;
case Node::Enum:
@ -310,7 +310,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
details << item.name(); // "name"
details << item.name(); // "id"
}
details << gen_->fullDocumentLocation(node,true);
details << gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
project.keywords.append(details);
}
}
@ -342,7 +342,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
if (node->relates()) {
project.memberStatus[node->relates()].insert(node->status());
project.files.insert(gen_->fullDocumentLocation(node->relates(),true));
project.files.insert(gen_->fullDocumentLocation(node->relates(),Generator::useOutputSubdirs()));
} else if (node->parent())
project.memberStatus[node->parent()].insert(node->status());
}
@ -356,7 +356,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
// Use the location of any associated enum node in preference
// to that of the typedef.
if (enumNode)
typedefDetails[2] = gen_->fullDocumentLocation(enumNode,true);
typedefDetails[2] = gen_->fullDocumentLocation(enumNode,Generator::useOutputSubdirs());
project.keywords.append(typedefDetails);
}
@ -364,7 +364,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
case Node::Variable:
{
QString location = gen_->fullDocumentLocation(node,true);
QString location = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
project.files.insert(location.left(location.lastIndexOf(QLatin1Char('#'))));
project.keywords.append(keywordDetails(node));
}
@ -385,18 +385,18 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
QStringList details;
details << keyword->string()
<< keyword->string()
<< gen_->fullDocumentLocation(node,true) +
<< gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()) +
QLatin1Char('#') + Doc::canonicalTitle(keyword->string());
project.keywords.append(details);
} else
docNode->doc().location().warning(
tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,true))
tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()))
);
}
}
project.keywords.append(keywordDetails(node));
}
project.files.insert(gen_->fullDocumentLocation(node,true));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
}
break;
}
@ -467,7 +467,8 @@ 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(),true));
project.files.insert(gen_->fullDocumentLocation(childNode->relates(),
Generator::useOutputSubdirs()));
}
if (childNode->type() == Node::Function) {
@ -523,7 +524,7 @@ void HelpProjectWriter::writeSection(QXmlStreamWriter &writer, const QString &pa
void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &writer,
const Node *node, bool writeSections)
{
QString href = gen_->fullDocumentLocation(node,true);
QString href = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
href = href.left(href.size()-5);
if (href.isEmpty())
return;
@ -561,7 +562,7 @@ void HelpProjectWriter::addMembers(HelpProject &project, QXmlStreamWriter &write
void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer,
const Node *node)
{
QString href = gen_->fullDocumentLocation(node,true);
QString href = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
QString objName = node->name();
switch (node->type()) {
@ -657,7 +658,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
node = qdb_->findNode(QStringList("index.html"));
QString indexPath;
if (node)
indexPath = gen_->fullDocumentLocation(node,true);
indexPath = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
else
indexPath = "index.html";
writer.writeAttribute("ref", indexPath);
@ -700,7 +701,8 @@ void HelpProjectWriter::generateProject(HelpProject &project)
const DocNode *page = qdb_->findDocNodeByTitle(atom->string());
writer.writeStartElement("section");
QString indexPath = gen_->fullDocumentLocation(page,true);
QString indexPath = gen_->fullDocumentLocation(page,
Generator::useOutputSubdirs());
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", atom->string());
project.files.insert(indexPath);
@ -725,7 +727,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (!name.isEmpty()) {
writer.writeStartElement("section");
QString indexPath = gen_->fullDocumentLocation(qdb_->findDocNodeByTitle(subproject.indexTitle),true);
QString indexPath = gen_->fullDocumentLocation(qdb_->findDocNodeByTitle(subproject.indexTitle),Generator::useOutputSubdirs());
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", subproject.title);
project.files.insert(indexPath);

View File

@ -2361,7 +2361,10 @@ QString HtmlGenerator::generateLowStatusMemberFile(InnerNode *inner,
fileName = fileBase(inner) + "-obsolete." + fileExtension();
}
if (status == CodeMarker::Obsolete) {
QString link = QString("../" + Generator::outputSubdir() + QLatin1Char('/')) + fileName;
QString link;
if (useOutputSubdirs() && !Generator::outputSubdir().isEmpty())
link = QString("../" + Generator::outputSubdir() + QLatin1Char('/'));
link += fileName;
inner->setObsoleteLink(link);
}
@ -2703,8 +2706,10 @@ void HtmlGenerator::generateCompactList(ListType listType,
}
else if (listType == Obsolete) {
QString fileName = fileBase(it.value()) + "-obsolete." + fileExtension();
QString link = QString("../" + it.value()->outputSubdirectory() +
QLatin1Char('/')) + fileName;
QString link;
if (useOutputSubdirs())
link = QString("../" + it.value()->outputSubdirectory() + QLatin1Char('/'));
link += fileName;
out() << "<a href=\"" << link << "\">";
}
@ -3598,7 +3603,7 @@ QString HtmlGenerator::linkForNode(const Node *node, const Node *relative)
back down into the other subdirectory.
*/
if (node && relative && (node != relative)) {
if (node->outputSubdirectory() != relative->outputSubdirectory())
if (useOutputSubdirs() && node->outputSubdirectory() != relative->outputSubdirectory())
link.prepend(QString("../" + node->outputSubdirectory() + QLatin1Char('/')));
}
return link;

View File

@ -274,6 +274,7 @@ public:
#define HTMLGENERATOR_POSTHEADER "postheader"
#define HTMLGENERATOR_POSTPOSTHEADER "postpostheader"
#define HTMLGENERATOR_NONAVIGATIONBAR "nonavigationbar"
#define HTMLGENERATOR_NOSUBDIRS "nosubdirs"
QT_END_NAMESPACE

View File

@ -165,6 +165,13 @@ static void loadIndexFiles(Config& config)
dependModules += config.getStringList(CONFIG_DEPENDS);
bool noOutputSubdirs = false;
QString singleOutputSubdir;
if (config.getBool(QString("HTML.nosubdirs"))) {
noOutputSubdirs = true;
singleOutputSubdir = config.getString("HTML.outputsubdir");
}
// Allow modules and third-party application/libraries to link
// to the Qt docs without having to explicitly pass --indexdir.
if (!indexDirs.contains(documentationPath))
@ -199,8 +206,12 @@ static void loadIndexFiles(Config& config)
QString indexToAdd;
QList<QFileInfo> foundIndices;
for (int j = 0; j < indexDirs.size(); j++) {
QString fileToLookFor = indexDirs[j] + QLatin1Char('/') + dependModules[i] +
QLatin1Char('/') + dependModules[i] + QLatin1String(".index");
QString fileToLookFor = indexDirs[j] + QLatin1Char('/');
if (noOutputSubdirs)
fileToLookFor += singleOutputSubdir + QLatin1Char('/');
else
fileToLookFor += dependModules[i] + QLatin1Char('/');
fileToLookFor += dependModules[i] + QLatin1String(".index");
if (QFile::exists(fileToLookFor)) {
QFileInfo tempFileInfo(fileToLookFor);
if (!foundIndices.contains(tempFileInfo))

View File

@ -763,7 +763,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QString fullName = node->fullDocumentName();
if (fullName != objName)
writer.writeAttribute("fullname", fullName);
QString href = node->outputSubdirectory();
QString href;
if (Generator::useOutputSubdirs())
href = node->outputSubdirectory();
if (!href.isEmpty())
href.append(QLatin1Char('/'));
href.append(gen_->fullDocumentLocation(node));

View File

@ -156,7 +156,7 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
if (node->type() == Node::Class) {
writer.writeTextElement("name", node->fullDocumentName());
writer.writeTextElement("filename", gen_->fullDocumentLocation(node,true));
writer.writeTextElement("filename", gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
// Classes contain information about their base classes.
const ClassNode* classNode = static_cast<const ClassNode*>(node);
@ -175,7 +175,7 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
}
else {
writer.writeTextElement("name", node->fullDocumentName());
writer.writeTextElement("filename", gen_->fullDocumentLocation(node,true));
writer.writeTextElement("filename", gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
// Recurse to write all members.
generateTagFileMembers(writer, static_cast<const InnerNode*>(node));
@ -291,7 +291,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
writer.writeTextElement("type", "virtual " + functionNode->returnType());
writer.writeTextElement("name", objName);
QStringList pieces = gen_->fullDocumentLocation(node,true).split(QLatin1Char('#'));
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
@ -332,7 +332,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
const PropertyNode* propertyNode = static_cast<const PropertyNode*>(node);
writer.writeAttribute("type", propertyNode->dataType());
writer.writeTextElement("name", objName);
QStringList pieces = gen_->fullDocumentLocation(node,true).split(QLatin1Char('#'));
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
writer.writeTextElement("arglist", QString());
@ -366,7 +366,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
else
writer.writeAttribute("type", QString());
writer.writeTextElement("name", objName);
QStringList pieces = gen_->fullDocumentLocation(node,true).split(QLatin1Char('#'));
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
writer.writeTextElement("arglist", QString());