Skip to content

Add configuration options to set rankdir for dot graphs #11440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

ulmus-scott
Copy link

@ulmus-scott ulmus-scott commented Feb 20, 2025

These commits add configuration options to set rankdir for dot graphs.

References #4453 see DOT_GRAPH_ATTR
References #9869 see DOT_RANKDIR_CLASS

I'm not sure what config.xml is supposed to include and setting a defval for DOT_GRAPH_ATTR caused it to print it in the generated doxyfile, but without the preceding newline and "# The default value is: ".

I kept the inverse behavior of the call graphs and the strange switching to LR with DotClassGraph.

The final commit is optional and changes VHDL flow charts, applying the other global attributes to the dot graph.

For quick testing I created a simple class hierarchy:
doxygen-test-rankdir.tar.gz

I started getting a nonsense warning from gcc after adding DOT_RANKDIR_DIR_DEP:

In file included from /home/scott/build/doxygen/src/types.h:19,
                 from /home/scott/build/doxygen/src/definition.h:21,
                 from /home/scott/build/doxygen/src/namespacedef.h:22,
                 from /home/scott/build/doxygen/src/namespacedef.cpp:18:
In function ‘int qstrcmp(const char*, const char*)’,
    inlined from ‘bool operator==(const QCString&, const char*)’ at /home/scott/build/doxygen/src/qcstring.h:611:17,
    inlined from ‘virtual bool NamespaceDefImpl::isLinkableInProject() const’ at /home/scott/build/doxygen/src/namespacedef.cpp:1537:23:
/home/scott/build/doxygen/src/qcstring.h:70:33: warning: ‘int strcmp(const char*, const char*)’ of a string of length 20 and an array of size 16 evaluates to nonzero [-Wstring-compare]
   70 | { return (str1 && str2) ? strcmp(str1,str2) :     // both non-empty
      |                           ~~~~~~^~~~~~~~~~~
/home/scott/build/doxygen/src/namespacedef.cpp: In member function ‘virtual bool NamespaceDefImpl::isLinkableInProject() const’:
/home/scott/build/doxygen/src/namespacedef.cpp:1536:21: note: in this expression
 1536 |   if (extractAnonNs &&                             // extract anonymous ns
      |       ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1537 |       name().mid(i,20)=="anonymous_namespace{"     // correct prefix
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I have not investigated, and am not planning on it, but it would also be nice if there were doxygen commands to be able to set the rankdir on a per graph basis, e.g. some graphs in the same category may be more compact LR, others TB.

@albert-github
Copy link
Collaborator

Thanks for the efforts.
The way doxygen handles PRs etc in respect to closing issues etc. is in such a way that the issues are kept open when a PR is merged until the next official release, as you used the sentence with "closes issue_number" GitHub has the (for doxygen bad) intelligence to add an automatic issue close on complete:
image

  • Please remove these 2 links (hitting the "wheel" and removing the check marks will probably do).

Regarding the compilation warning, strange. I don't see at first glance what could be wrong.

  • which compiler and compiler version did you use?

The code itself, I have to study it a bit and will write comments to the code later on.

Regarding:

I have not investigated, and am not planning on it, but it would also be nice if there were doxygen commands to be able to set the rankdir on a per graph basis, e.g. some graphs in the same category may be more compact LR, others TB.

No there is no no doxygen command to set any attribute on a per graph base, would probably be a nice enhancement but quite difficult seen the different possibilities for all graphs (especially inheritance / collaboration graphs). I think the command should not be limited to just the rankdir but also have other attribute possibilities (and maybe even the possibility of setting the maximum number of nodes of a particular graph, which is now a global settings number). I think these remarks might also be valid for the settings as done here which is limited to just the rankdir. This will need some serious thinking and definition I think.

Copy link
Collaborator

@albert-github albert-github left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this many extra settings. I already made some comments about this in #11440 (comment) and the total concept of handling the attributes for dot should in my opinion be reconsidered.

\c DOT_GRAPH_ATTR is common attributes for graphs.
For details please see
<a href="https://graphviz.org/doc/info/attrs.html">Node, Edge and Graph Attributes specification</a>.
<br>The default value is:<br>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text for the default value is generated automatically, so sentence should not be here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except when I run doxygen -g, the sentence isn't generated but the value is inserted (with a period after and no space or new line).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the behavior is different since this is type='list' not type='string'.

@@ -3802,6 +3802,130 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
]]>
</docs>
</option>
<option type='list' id='DOT_GRAPH_ATTR' format='string' depends='HAVE_DOT'
defval='bgcolor=\"transparent\"'>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the double quotes should be escaped (\"), it is not necssary as the string is embedded in single quotes , probably the double quotes can removed all together (see e.g. DOT_COMMON_ATTR)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Escaping the double quotes is necessary to create the same output as before:

  bgcolor="transparent";

I think having un-escaped " would confuse the parsing of the doxyfile?

You are correct that dot also accepts bgcolor=transparent, but I was trying to keep the output the same.

</docs>
<value name='bgcolor=\"transparent\"'/>
</option>
<option type='string' id='DOT_RANKDIR_CALL' format='string' depends='HAVE_DOT' defval='LR'>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the default be the empty string?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If DotCallGraph::m_inverse was false, rankdir was "LR". I am trying to preserve the previous behavior.

Comment on lines +167 to +171
QCString rankdir = Config_getString(DOT_RANKDIR_CALL);
if (rankdir.size() >= 2 && m_inverse)
{
std::swap(rankdir[0], rankdir[1]);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you get 2 or more values on the rankdir part?
What happens with the values 3, 4, ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rankdir is supposed to be only "TB", "BT", "LR", or "RL"; this is supposed to swap the characters in the string: "TB" becomes "BT", etc.

My version of dot appeared to reset to its default (TB) if given an invalid string, e.g. "foo", so I saw no reason to explicitly check and replace when swapping does the same thing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which version of dot do you use?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dot -V
dot - graphviz version 2.43.0 (0)

I had tested the behavior with an invalid rankdir using a valid rankdir in DOT_GRAPH_ATTR and setting an invalid DOT_RANKDIR_INCLUDE.

@ulmus-scott
Copy link
Author

Thanks for the efforts. The way doxygen handles PRs etc in respect to closing issues etc. is in such a way that the issues are kept open when a PR is merged until the next official release, as you used the sentence with "closes issue_number" GitHub has the (for doxygen bad) intelligence to add an automatic issue close on complete: image

* Please remove these 2 links (hitting the "wheel" and removing the check marks will probably do).

I did not see the gear icon, but replacing "closes" with "references" in the comment appears to have removed it.

Regarding the compilation warning, strange. I don't see at first glance what could be wrong.

* which compiler and compiler version did you use?
gcc --version
gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0

The code itself, I have to study it a bit and will write comments to the code later on.

Regarding:

I have not investigated, and am not planning on it, but it would also be nice if there were doxygen commands to be able to set the rankdir on a per graph basis, e.g. some graphs in the same category may be more compact LR, others TB.

No there is no no doxygen command to set any attribute on a per graph base, would probably be a nice enhancement but quite difficult seen the different possibilities for all graphs (especially inheritance / collaboration graphs). I think the command should not be limited to just the rankdir but also have other attribute possibilities (and maybe even the possibility of setting the maximum number of nodes of a particular graph, which is now a global settings number). I think these remarks might also be valid for the settings as done here which is limited to just the rankdir. This will need some serious thinking and definition I think.

Adding commands to supply dot statements that would be inserted at the end of DotGraph::writeGraphHeader(), probably replacing the new rankdir parameter and similar to how DOT_GRAPH_ATTR works, would probably work. I don't know how the maximum number of nodes is set, so that may also be possible via the same proposed commands.

Generalizing this from rankdir to any graph attribute would probably require changes to how DotClassGraph and DotCallGraph behave.

With DotClassGraph's unique dynamic selection of rankdir, it would be easiest to remove, but maybe something like:

auto attributes = getConfig(DOT_ATTR_CLASS);
if (!attributes.contains("rankdir") && m_lrRank)
{
    attributes.append("rankdir=\"LR\"");
}

DotCallGraph's inverse direction may be achieved with appending edge [dir=back] (https://graphviz.org/docs/attrs/dir/), but I would need to test it to be sure.

I'm not a fan of this many extra settings. I already made some comments about this in #11440 (comment) and the total concept of handling the attributes for dot should in my opinion be reconsidered.

I don't think this is significantly different to how the dot graphs are already handled. See https://www.doxygen.nl/manual/commands.html#cmdgroupgraph, etc.; and the configuration options: CLASS_GRAPH, COLLABORATION_GRAPH, GROUP_GRAPHS, TEMPLATE_RELATIONS, INCLUDE_GRAPH, INCLUDED_BY_GRAPH, CALL_GRAPH, CALLER_GRAPH, GRAPHICAL_HIERARCHY, and DIRECTORY_GRAPH.

@ulmus-scott
Copy link
Author

DotCallGraph's inverse direction may be achieved with appending edge [dir=back] (https://graphviz.org/docs/attrs/dir/), but I would need to test it to be sure.

edge [dir=back] only reverses the direction of the arrows, i.e. A->B shows as A<-B, the position of the nodes in the rendered graph remain the same, so extracting rankdir from the attribute list would be required to reverse/mirror it.

@ulmus-scott
Copy link
Author

doxygen-test-rankdir_with-call-graphs.tar.gz
If you set DOT_RANKDIR_CALL = foo in Doxyfile, the call graphs will all be TB (default) and the .dot files will show either rankdir="foo"; (e.g. structLevel0_a6116ba32d0d153509eb40e6b95b50345_cgraph.dot) or rankdir="ofo"; (e.g. structLevel0_a6116ba32d0d153509eb40e6b95b50345_icgraph.dot). Of course, it also works correctly as expected with the valid LR, RL, TB, and BT rankdirs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy