101 if (tooltip.
isEmpty())
return tooltip;
103 const char *p=tooltip.
data();
109 case '"': result+=
"\\\"";
break;
110 case '\\': result+=
"\\\\";
break;
111 default: result+=c;
break;
122 constexpr auto tr_start =
"<TR><TD VALIGN=\"top\" CELLPADDING=\"1\" CELLSPACING=\"0\">";
123 constexpr auto tr_mid =
"</TD><TD VALIGN=\"top\" ALIGN=\"LEFT\" CELLPADDING=\"1\" CELLSPACING=\"0\">";
124 constexpr auto tr_end =
"</TD></TR>\n";
125 constexpr auto br =
"<BR ALIGN=\"LEFT\"/>";
130 for (
const auto &mma : *ml)
132 if (mma->getClassDef()==scope &&
133 (skipNames==
nullptr || skipNames->find(mma->name().str())==std::end(*skipNames)) &&
134 !(hideUndocMembers && !mma->hasDocumentation())
143 for (
const auto &mma : *ml)
145 if (mma->getClassDef() == scope &&
146 (skipNames==
nullptr || skipNames->find(mma->name().str())==std::end(*skipNames)) &&
147 !(hideUndocMembers && !mma->hasDocumentation())
151 if (numFields>0 && (totalCount>numFields*3/2 && count>=numFields))
153 t << tr_start << tr_mid <<
theTranslator->trAndMore(
QCString().sprintf(
"%d",totalCount-count)) << tr_end;
159 t << tr_start << prot << tr_mid;
161 if (dotUmlDetails==DOT_UML_DETAILS_t::YES)
163 label+=mma->typeString();
167 if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal()))
169 if (dotUmlDetails==DOT_UML_DETAILS_t::YES)
171 label+=mma->argsString();
186 for (
const auto &mg : ml->getMemberGroupList())
188 if (!mg->members().empty())
198 QCString bBefore(
"\\_/<({[: =-+@%#~?$");
205 int charsLeft=
static_cast<int>(p.
length());
210 br =
"<BR ALIGN=\"LEFT\"/>";
216 char cs[2] = { c, 0 };
217 const char *replacement = cs;
222 case '\\': replacement=
"\\\\";
break;
223 case '\n': replacement=
"\\n";
break;
224 case '<': replacement=
"<";
break;
225 case '>': replacement=
">";
break;
226 case '"': replacement=
""";
break;
227 case '\'': replacement=
"'";
break;
228 case '&': replacement=
"&";
break;
235 case '\\': replacement=
"\\\\";
break;
236 case '\n': replacement=
"\\n";
break;
237 case '<': replacement=
"\\<";
break;
238 case '>': replacement=
"\\>";
break;
239 case '"': replacement=
"\\\"";
break;
240 case '|': replacement=
"\\|";
break;
241 case '{': replacement=
"\\{";
break;
242 case '}': replacement=
"\\}";
break;
250 foldLen = (3*foldLen+sinceLast+2)/4;
253 else if ((pc!=
':' || c!=
':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.
contains(c))
257 foldLen = (foldLen+sinceLast+1)/2;
260 else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 &&
261 !isupper(c) && isupper(p[idx]))
265 foldLen = (foldLen+sinceLast+1)/2;
268 else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.
contains(c) && (c!=
':' || p[idx]!=
':'))
272 foldLen = (foldLen+sinceLast+1)/2;
292 if (!s.
isEmpty() && (s[0]==
'-' || s[0]==
'+' || s[0]==
'~' || s[0]==
'#'))
305 ,
m_number(graph->getNextNodeNumber())
328 edgeLabCol==-1 ? edgeColor : edgeLabCol);
355 pn->deleteNode(deletedList);
360 cn->deleteNode(deletedList);
363 deletedList.push_back(
this);
384 for (
const auto &dotNode : deletedNodes)
396 t <<
"shape=plain,label=";
403 if (!ei.label().isEmpty())
408 while ((i=ei.label().find(
'\n',p))!=-1)
411 arrowNames.insert(lab.
str());
415 arrowNames.insert(lab.
str());
419 constexpr auto hr_start =
"<TR><TD COLSPAN=\"2\" CELLPADDING=\"1\" CELLSPACING=\"0\">";
420 constexpr auto hr_end =
"</TD></TR>\n";
421 constexpr auto sep =
"<HR/>\n";
422 constexpr auto empty_line =
"<TR><TD COLSPAN=\"2\" CELLPADDING=\"1\" CELLSPACING=\"0\"> </TD></TR>\n";
424 t <<
"<<TABLE CELLBORDER=\"0\" BORDER=\"1\">";
427 if (dotUmlDetails!=DOT_UML_DETAILS_t::NONE)
429 bool lineWritten =
false;
443 if (!lineWritten) t << empty_line;
462 for (
const auto &mg :
m_classDef->getMemberGroups())
464 if (!mg->members().empty())
470 if (!lineWritten) t << empty_line;
493 int tagPos =
m_url.findRev(
'$');
498 t <<
m_url.left(tagPos);
499 noTagURL =
m_url.mid(tagPos);
501 int anchorPos = noTagURL.
findRev(
'#');
505 t << noTagURL <<
"\"";
511 t << fn << noTagURL.
right(noTagURL.
length() - anchorPos) <<
"\"";
518 bool hasNonReachableChildren)
const
520 const char *labCol =
nullptr;
521 const char *fillCol =
"white";
524 if (
m_classDef->hasDocumentation() && hasNonReachableChildren)
529 else if (
m_classDef->hasDocumentation() && !hasNonReachableChildren)
533 else if (!
m_classDef->hasDocumentation() && hasNonReachableChildren)
535 labCol =
"orangered";
548 labCol =
m_url.isEmpty() ?
"grey60" :
549 (hasNonReachableChildren ?
"red" :
"grey40");
550 fillCol =
m_url.isEmpty() ?
"#E0E0E0" :
551 (hasNonReachableChildren ?
"#FFF0F0" :
"white");
556 t <<
",height=0.2,width=0.4";
559 t <<
",color=\"gray40\", fillcolor=\"grey60\", style=\"filled\", fontcolor=\"black\"";
563 t <<
",color=\"" << labCol <<
"\"";
564 t <<
", fillcolor=\"" << fillCol <<
"\"";
565 t <<
", style=\"filled\"";
574 t <<
",tooltip=\" \"";
585 bool pointBack)
const
601 bool umlUseArrow = aStyle==
"odiamond";
603 t <<
"id=\"edge" <<
m_graph->getNextEdgeNumber() <<
606 if (pointBack && !umlUseArrow) t <<
"dir=\"back\",";
609 t <<
",tooltip=\" \"";
619 bool rev = pointBack;
620 if (umlUseArrow) rev=!rev;
650 writeArrow(t,gt,format,cn,&(*it),topDown,backArrows);
652 cn->write(t,gt,format,topDown,toChildren,backArrows);
662 const auto &
children = pn->children();
664 size_t index = child_it -
children.begin();
670 &pn->edgeInfo()[index],
675 pn->write(t,gt,format,
TRUE,
FALSE,backArrows);
683 t <<
" <node id=\"" <<
m_number <<
"\">\n";
685 if (!
m_url.isEmpty())
688 int dollarPos = url.
find(
'$');
703 t <<
" <childnode refid=\"" << childNode->number() <<
"\" relation=\"";
726 while ((ni=
edgeInfo.label().find(
'\n',p))!=-1)
737 t <<
" </childnode>\n";
745 t <<
" <node id=\"" <<
m_number <<
"\">\n";
747 if (!
m_url.isEmpty())
750 int dollarPos = url.
find(
'$');
765 t <<
" <childnode refid=\"" << childNode->number() <<
"\" relation=\"";
788 while ((ni=
edgeInfo.label().find(
'\n',p))!=-1)
799 t <<
" </childnode>\n";
808 const char* nodePrefix =
" node-";
811 t << nodePrefix <<
"id = " <<
m_number <<
";\n";
812 t << nodePrefix <<
"label = '" <<
m_label <<
"';\n";
814 if (!
m_url.isEmpty())
817 int dollarPos = url.
find(
'$');
820 t << nodePrefix <<
"link = {\n" <<
" "
821 << nodePrefix <<
"link-id = '" << url.
mid(dollarPos+1) <<
"';\n";
824 t <<
" " << nodePrefix <<
"link-external = '"
825 << url.
left(dollarPos) <<
"';\n";
834 t <<
" node-child = {\n";
835 t <<
" child-id = '" << childNode->number() <<
"';\n";
852 t <<
" edgelabel = <<_EnD_oF_dEf_TeXt_\n"
854 <<
"_EnD_oF_dEf_TeXt_;\n";
856 t <<
" }; /* node-child */\n";
859 t <<
" }; /* node */\n";
866 for (
const auto &pn :
m_parents)
if (pn->isWritten()) pn->clearWriteFlag();
867 for (
const auto &cn :
m_children)
if (cn->isWritten()) cn->clearWriteFlag();
874 if (cn->subgraphId()==-1)
876 cn->setSubgraphId(curColor);
878 cn->colorConnectedNodes(curColor);
885 if (pn->subgraphId()==-1)
887 pn->setSubgraphId(curColor);
889 pn->colorConnectedNodes(curColor);
895#define DEBUG_RENUMBERING 0
902 static int level = 0;
904 for (
int i = 0; i < level; i++) printf(
" ");
912 cn->renumberNodes(
number);
916 pn->renumberNodes(
number);
921 for (
int i = 0; i < level; i++) printf(
" ");
A abstract class representing of a compound symbol.
void writeDEF(TextStream &t) const
int findParent(DotNode *n)
void writeUrl(TextStream &t) const
QCString m_tooltip
node's tooltip
void setDistance(int distance)
void write(TextStream &t, GraphType gt, GraphOutputFormat f, bool topDown, bool toChildren, bool backArrows)
bool m_isRoot
indicates if this is a root node
void removeParent(DotNode *n)
QCString m_label
label text
const EdgeInfoVector & edgeInfo() const
void writeBox(TextStream &t, GraphType gt, GraphOutputFormat f, bool hasNonReachableChildren) const
TruncState m_truncated
does the node have non-visible children/parents
DotNode(DotGraph *graph, const QCString &lab, const QCString &tip, const QCString &url, bool rootNode=FALSE, const ClassDef *cd=nullptr)
void writeDocbook(TextStream &t, bool isClassGraph) const
void renumberNodes(int &number)
bool m_written
used to mark a node as written
void removeChild(DotNode *n)
static void deleteNodes(DotNode *node)
static QCString convertLabel(const QCString &, bool htmlLike=false)
EdgeInfoVector m_edgeInfo
edge info for each child
bool isRenumbered() const
int m_distance
shortest path to the root node
void addParent(DotNode *n)
DotNodeRefVector m_parents
list of parent nodes (incoming arrows)
bool m_visible
is the node visible in the output
void colorConnectedNodes(int curColor)
DotNodeRefVector m_children
list of child nodes (outgoing arrows)
void addChild(DotNode *n, EdgeInfo::Colors edgeColor=EdgeInfo::Purple, EdgeInfo::Styles edgeStyle=EdgeInfo::Solid, const QCString &edgeLab=QCString(), const QCString &edgeURL=QCString(), int edgeLabCol=-1)
const ClassDef * m_classDef
class representing this node (can be 0)
static constexpr auto placeholderUrl
const DotNodeRefVector & children() const
bool m_deleted
used to mark a node as deleted
void deleteNode(DotNodeRefVector &deletedList)
void writeLabel(TextStream &t, GraphType gt) const
void writeArrow(TextStream &t, GraphType gt, GraphOutputFormat f, const DotNode *cn, const EdgeInfo *ei, bool topDown, bool pointBack=TRUE) const
void writeXML(TextStream &t, bool isClassGraph) const
QCString m_url
url of the node (format: remote$local)
Attributes of an edge of a dot graph.
A list of MemberDef objects as shown in documentation sections.
This is an alternative implementation of QCString.
int find(char c, int index=0, bool cs=TRUE) const
size_t length() const
Returns the length of the string, not counting the 0-terminator.
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
bool isEmpty() const
Returns TRUE iff the string is empty.
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
const std::string & str() const
QCString right(size_t len) const
QCString & sprintf(const char *format,...)
int findRev(char c, int index=-1, bool cs=TRUE) const
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
QCString left(size_t len) const
int contains(char c, bool cs=TRUE) const
Text streaming class that buffers data.
#define Config_getInt(name)
#define Config_getBool(name)
#define Config_getString(name)
#define Config_getEnum(name)
std::unordered_set< std::string > StringUnorderedSet
static const char * normalEdgeColorMap[]
static const char * normalEdgeStyleMap[]
static EdgeProperties normalEdgeProps
QCString escapeTooltip(const QCString &tooltip)
static const char * umlEdgeStyleMap[]
static const char * normalArrowStyleMap[]
static EdgeProperties umlEdgeProps
static const char * umlEdgeColorMap[]
static QCString stripProtectionPrefix(const QCString &s)
static void writeBoxMemberList(TextStream &t, char prot, const MemberList *ml, const ClassDef *scope, bool &lineWritten, bool isStatic=FALSE, const StringUnorderedSet *skipNames=nullptr)
static const char * umlArrowStyleMap[]
std::vector< DotNode * > DotNodeRefVector
QCString escapeTooltip(const QCString &tooltip)
Translator * theTranslator
const char * qPrint(const char *s)
Helper struct holding the properties of a edge in a dot graph.
const char *const * arrowStyleMap
const char *const * edgeStyleMap
const char *const * edgeColorMap
QCString convertToXML(const QCString &s, bool keepEntities)
void addHtmlExtensionIfMissing(QCString &fName)
A bunch of utility functions.