50bool XmlGenerator::isOneColumnValueTable(
const Atom *atom)
52 if (atom->type() != Atom::ListLeft || atom->string() !=
ATOM_LIST_VALUE)
55 while (atom && atom->type() != Atom::ListTagRight)
59 if (!matchAhead(atom, Atom::ListItemLeft))
63 return matchAhead(atom->next(), Atom::ListItemRight);
100void XmlGenerator::rewritePropertyBrief(
const Atom *atom,
const Node *relative)
102 if (relative->nodeType() != NodeType::Property && relative->nodeType() != NodeType::Variable)
105 if (!atom || atom->type() != Atom::String)
108 const QString firstWord =
109 atom->string().toLower().section(
' ', 0, 0, QString::SectionSkipEmpty);
110 const QStringList words{
"the",
"a",
"an",
"whether",
"which" };
111 if (words.contains(firstWord)) {
112 QString str = QLatin1String(
"This ")
113 + QLatin1String(relative->nodeType() == NodeType::Property ?
"property" :
"variable")
114 + QLatin1String(
" holds ") + atom->string().left(1).toLower()
115 + atom->string().mid(1);
116 const_cast<Atom *>(atom)->setString(str);
138void XmlGenerator::setImageFileName(
const Node *relative,
const QString &fileName)
140 if (relative->isExample()) {
141 const auto cen =
static_cast<
const ExampleNode *>(relative);
142 if (cen->imageFileName().isEmpty()) {
143 auto *en =
const_cast<ExampleNode *>(cen);
144 en->setImageFileName(fileName);
154std::pair<QString,
int> XmlGenerator::getAtomListValue(
const Atom *atom)
156 const Atom *lookAhead = atom->next();
158 return std::pair<QString,
int>(QString(), 1);
160 QString t = lookAhead->string();
161 lookAhead = lookAhead->next();
162 if (!lookAhead || lookAhead->type() != Atom::ListTagRight)
163 return std::pair<QString,
int>(QString(), 1);
165 lookAhead = lookAhead->next();
167 if (lookAhead && lookAhead->type() == Atom::SinceTagLeft) {
168 lookAhead = lookAhead->next();
169 Q_ASSERT(lookAhead && lookAhead->type() == Atom::String);
170 t += QLatin1String(
" (since ");
171 const QString sinceString = lookAhead->string();
172 if (sinceString.at(0).isDigit()) {
174 t += productName.isEmpty() ? sinceString : productName +
" " + sinceString;
178 t += QLatin1String(
")");
183 return std::pair<QString,
int>(t, skipAhead);
192std::pair<QString, QString> XmlGenerator::getTableWidthAttr(
const Atom *atom)
195 QString attr =
"generic";
197 if (atom->count() > 0) {
198 p0 = atom->string(0);
199 if (atom->count() > 1)
200 p1 = atom->string(1);
203 if (p0 == QLatin1String(
"borderless"))
205 else if (p0.contains(QLatin1Char(
'%')))
209 if (p1 == QLatin1String(
"borderless"))
210 attr = std::move(p1);
211 else if (p1.contains(QLatin1Char(
'%')))
212 width = std::move(p1);
217 if (width == QLatin1String(
"%")) {
220 int widthPercentage = p0.toInt(&ok);
222 width = QString::number(widthPercentage) +
"%";
228 return {width, attr};
262QString XmlGenerator::refForNode(
const Node *node)
265 switch (node->nodeType()) {
267 case NodeType::QmlEnum:
268 ref = node->name() +
"-enum";
270 case NodeType::Typedef: {
271 const auto *tdf =
static_cast<
const TypedefNode *>(node);
272 if (tdf->associatedEnum())
273 return refForNode(tdf->associatedEnum());
275 case NodeType::TypeAlias:
276 ref = node->name() +
"-typedef";
278 case NodeType::Function: {
279 const auto fn =
static_cast<
const FunctionNode *>(node);
280 switch (fn->metaness()) {
281 case FunctionNode::QmlSignal:
282 ref = fn->name() +
"-signal";
284 case FunctionNode::QmlSignalHandler:
285 ref = fn->name() +
"-signal-handler";
287 case FunctionNode::QmlMethod:
288 ref = fn->name() +
"-method";
289 if (fn->overloadNumber() != 0)
290 ref += QLatin1Char(
'-') + QString::number(fn->overloadNumber());
293 if (
const auto *p = fn->primaryAssociatedProperty(); p && fn->doc().isEmpty()) {
294 return refForNode(p);
297 if (fn->overloadNumber() != 0)
298 ref += QLatin1Char(
'-') + QString::number(fn->overloadNumber());
303 case NodeType::SharedComment: {
304 if (!node->isPropertyGroup())
307 case NodeType::QmlProperty:
308 if (node->isAttached())
309 ref = node->name() +
"-attached-prop";
311 ref = node->name() +
"-prop";
313 case NodeType::Property:
314 ref = node->name() +
"-prop";
316 case NodeType::Variable:
317 ref = node->name() +
"-var";
322 return registerRef(ref);
334QString XmlGenerator::linkForNode(
const Node *node,
const Node *relative)
338 if (!node->url().isNull())
340 if (fileBase(node).isEmpty())
342 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
343 const NodeContext context = node->createContext();
344 if (!InclusionFilter::isIncluded(policy, context))
347 QString fn = fileName(node);
348 if (node->parent() && node->parent()->isQmlType() && node->parent()->isAbstract()) {
349 if (Generator::qmlTypeContext()) {
350 if (Generator::qmlTypeContext()->inherits(node->parent())) {
351 fn = fileName(Generator::qmlTypeContext());
352 }
else if (node->parent()->isInternal() && !noLinkErrors()) {
353 node->doc().location().warning(
354 QStringLiteral(
"Cannot link to property in internal type '%1'")
355 .arg(node->parent()->name()));
363 if (!node->isPageNode() || node->isPropertyGroup()) {
364 QString ref = refForNode(node);
365 if (relative && fn == fileName(relative) && ref == refForNode(relative))
368 link += QLatin1Char(
'#');
373
374
375
376
377
378
379
380 if (relative && (node != relative)) {
381 if (useOutputSubdirs() && !node->isExternalPage() &&
382 (node->isIndexNode() || node->tree() != relative->tree()))
383 link.prepend(
"../%1/"_L1.arg(node->tree()->physicalModuleName()));
433QString XmlGenerator::getAutoLink(
const Atom *atom,
const Node *relative,
const Node **node,
438 *node = m_qdb->findNodeForAtom(atom, relative, ref, genus);
442 QString link = (*node)->url();
444 link = linkForNode(*node, relative);
445 }
else if (link.isEmpty()) {
448 if (!ref.isEmpty()) {
449 qsizetype hashtag = link.lastIndexOf(QChar(
'#'));
451 link.truncate(hashtag);
452 link += QLatin1Char(
'#') + ref;
457std::pair<QString, QString> XmlGenerator::anchorForNode(
const Node *node)
459 std::pair<QString, QString> anchorPair;
461 anchorPair.first = Generator::fileName(node);
462 if (node->isTextPageNode())
463 anchorPair.second = node->title();