2 * Copyright (C) 2008 by Sebastian Pipping.
3 * Copyright (C) 2008 Dimitri van Heesch.
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
14 * Sebastian Pipping <sebastian@pipping.org>
18 #include "qhpxmlwriter.h"
21 #include "memberdef.h"
26 #include <qstringlist.h>
29 static QCString makeFileName(const char * withoutExtension)
31 QCString result=withoutExtension;
32 if (!result.isEmpty())
34 if (result.at(0)=='!') // relative URL -> strip marker
38 else // add specified HTML extension
40 result+=Doxygen::htmlFileExtension;
46 static QCString makeRef(const char * withoutExtension, const char * anchor)
48 //printf("QHP::makeRef(%s,%s)\n",withoutExtension,anchor);
49 if (!withoutExtension) return QCString();
50 QCString result = makeFileName(withoutExtension);
51 if (!anchor) return result;
52 return result+"#"+anchor;
55 Qhp::Qhp() : m_prevSectionLevel(0), m_sectionLevel(0)
57 m_doc.setIndentLevel(0);
58 m_toc.setIndentLevel(2);
59 m_index.setIndentLevel(2);
60 m_files.setIndentLevel(2);
68 void Qhp::initialize()
71 <QtHelpProject version="1.0">
72 <namespace>mycompany.com.myapplication.1_0</namespace>
73 <virtualFolder>doc</virtualFolder>
74 <customFilter name="My Application 1.0">
75 <filterAttribute>myapp</filterAttribute>
76 <filterAttribute>1.0</filterAttribute>
79 <filterAttribute>myapp</filterAttribute>
80 <filterAttribute>1.0</filterAttribute>
83 QCString nameSpace = Config_getString("QHP_NAMESPACE");
84 QCString virtualFolder = Config_getString("QHP_VIRTUAL_FOLDER");
86 const char * rootAttributes[] =
87 { "version", "1.0", 0 };
89 m_doc.open("QtHelpProject", rootAttributes);
90 m_doc.openCloseContent("namespace", nameSpace);
91 m_doc.openCloseContent("virtualFolder", virtualFolder);
94 QCString filterName = Config_getString("QHP_CUST_FILTER_NAME");
95 if (!filterName.isEmpty())
97 const char * tagAttributes[] =
98 { "name", filterName, 0 };
99 m_doc.open("customFilter", tagAttributes);
101 QStringList customFilterAttributes = QStringList::split(QChar(' '), Config_getString("QHP_CUST_FILTER_ATTRS"));
102 for (int i = 0; i < (int)customFilterAttributes.count(); i++)
104 m_doc.openCloseContent("filterAttribute", customFilterAttributes[i].utf8());
106 m_doc.close("customFilter");
109 m_doc.open("filterSection");
111 // Add section attributes
112 QStringList sectionFilterAttributes = QStringList::split(QChar(' '),
113 Config_getString("QHP_SECT_FILTER_ATTRS"));
114 if (!sectionFilterAttributes.contains(QString("doxygen")))
116 sectionFilterAttributes << "doxygen";
118 for (int i = 0; i < (int)sectionFilterAttributes.count(); i++)
120 m_doc.openCloseContent("filterAttribute", sectionFilterAttributes[i].utf8());
125 // Add extra root node
126 QCString fullProjectname = getFullProjectName();
127 const char * const attributes[] =
128 { "title", fullProjectname,
129 "ref", QCString("index")+Doxygen::htmlFileExtension,
132 m_toc.open("section", attributes);
133 m_prevSectionTitle = getFullProjectName();
134 m_prevSectionLevel = 1;
137 m_index.open("keywords");
138 m_files.open("files");
145 for (int i = m_prevSectionLevel; i > 0; i--)
147 m_toc.close("section");
153 m_index.close("keywords");
154 m_doc.insert(m_index);
157 m_files.close("files");
158 m_doc.insert(m_files);
160 m_doc.close("filterSection");
161 m_doc.close("QtHelpProject");
163 QCString fileName = Config_getString("HTML_OUTPUT") + "/" + getQhpFileName();
164 QFile file(fileName);
165 if (!file.open(IO_WriteOnly))
167 err("Could not open file %s for writing\n", fileName.data());
173 void Qhp::incContentsDepth()
176 //printf("Qhp::incContentsDepth() %d->%d\n",m_sectionLevel-1,m_sectionLevel);
179 void Qhp::decContentsDepth()
181 //printf("Qhp::decContentsDepth() %d->%d\n",m_sectionLevel,m_sectionLevel-1);
182 if (m_sectionLevel <= 0)
189 void Qhp::addContentsItem(bool /*isDir*/, const char * name,
190 const char * /*ref*/, const char * file,
191 const char * /*anchor*/,bool /* separateIndex */,
192 bool /* addToNavIndex */,
193 Definition * /*def*/)
195 //printf("Qhp::addContentsItem(%s) %d\n",name,m_sectionLevel);
196 // Backup difference before modification
199 if (!f.isEmpty() && f.at(0)=='^') return; // absolute URL not supported
201 int diff = m_prevSectionLevel - m_sectionLevel;
204 setPrevSection(name, f, m_sectionLevel);
206 // Close sections as needed
207 for (; diff > 0; diff--)
209 m_toc.close("section");
213 void Qhp::addIndexItem(Definition *context,MemberDef *md,
217 //printf("addIndexItem(%s %s %s\n",
218 // context?context->name().data():"<none>",
219 // md?md->name().data():"<none>",
224 static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES");
225 if (context==0) // global member
227 if (md->getGroupDef())
228 context = md->getGroupDef();
229 else if (md->getFileDef())
230 context = md->getFileDef();
232 if (context==0) return; // should not happen
233 QCString cfname = md->getOutputFileBase();
234 QCString cfiname = context->getOutputFileBase();
235 QCString level1 = context->name();
236 QCString level2 = word ? QCString(word) : md->name();
237 QCString contRef = separateMemberPages ? cfname : cfiname;
238 QCString anchor = md->anchor();
242 // <keyword name="foo" id="MyApplication::foo" ref="doc.html#foo"/>
243 ref = makeRef(contRef, anchor);
244 QCString id = level1+"::"+level2;
245 const char * attributes[] =
252 m_index.openClose("keyword", attributes);
254 else if (context) // container
256 // <keyword name="Foo" id="Foo" ref="doc.html"/>
257 QCString contRef = context->getOutputFileBase();
258 QCString level1 = word ? QCString(word) : context->name();
259 QCString ref = makeFileName(contRef);
260 const char * attributes[] =
267 m_index.openClose("keyword", attributes);
271 void Qhp::addIndexFile(const char * name)
276 QCString Qhp::getQhpFileName()
281 QCString Qhp::getFullProjectName()
283 QCString projectName = Config_getString("PROJECT_NAME");
284 QCString versionText = Config_getString("PROJECT_NUMBER");
285 if (projectName.isEmpty()) projectName="Root";
286 return projectName + (versionText.isEmpty()
288 : QCString(" ") + versionText);
291 void Qhp::handlePrevSection()
295 <section title="My Application Manual" ref="index.html">
296 <section title="Chapter 1" ref="doc.html#chapter1"/>
297 <section title="Chapter 2" ref="doc.html#chapter2"/>
298 <section title="Chapter 3" ref="doc.html#chapter3"/>
303 if (m_prevSectionTitle.isNull())
305 m_prevSectionTitle=" "; // should not happen...
308 // We skip "Main Page" as our extra root is pointing to that
309 if (!((m_prevSectionLevel==1) && (m_prevSectionTitle==getFullProjectName())))
311 QCString finalRef = makeFileName(m_prevSectionRef);
313 const char * const attributes[] =
314 { "title", m_prevSectionTitle,
319 if (m_prevSectionLevel < m_sectionLevel)
321 // Section with children
322 m_toc.open("section", attributes);
326 // Section without children
327 m_toc.openClose("section", attributes);
334 void Qhp::setPrevSection(const char * title, const char * ref, int level)
336 m_prevSectionTitle = title;
337 m_prevSectionRef = ref;
338 m_prevSectionLevel = level;
341 void Qhp::clearPrevSection()
343 m_prevSectionTitle.resize(0);
344 m_prevSectionRef.resize(0);
347 void Qhp::addFile(const char * fileName)
349 m_files.openCloseContent("file", fileName);
352 void Qhp::addImageFile(const char *fileName)
357 void Qhp::addStyleSheetFile(const char *fileName)