Skip to content

Commit 4f3a4c5

Browse files
committed
Merge branch 'master' into feature/bug_blockquote_section
2 parents d8bdc0f + 791bcf8 commit 4f3a4c5

29 files changed

+493
-91
lines changed

addon/doxycommentview/doxycommentview.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import argparse
2222
import signal
2323
import threading
24+
import html
2425

2526
def main():
2627
# Set up argument parser
@@ -33,6 +34,7 @@ def main():
3334
PORT = args.port
3435
DOXYGEN = args.doxygen
3536
DOXYFILE = args.doxyfile
37+
VERSION_STR = subprocess.run([DOXYGEN, '-v'], capture_output=True, text=True, encoding="utf-8").stdout
3638

3739
class RequestHandler(http.server.SimpleHTTPRequestHandler):
3840
def do_POST(self):
@@ -42,15 +44,21 @@ def do_POST(self):
4244
data = json.loads(post_data)
4345
input_text = data['input']
4446

45-
# Run doxygen in single comment mode, reading from stdin and writing to stdout
47+
# Run doxygen in single comment mode, reading from stdin and writing to stdout and stderr
4648
result = subprocess.run([DOXYGEN, '-c', '-', DOXYFILE], \
4749
input=input_text, capture_output=True, text=True, encoding="utf-8")
4850

49-
# Insert CSS link tag into the HTML output
51+
# Prepare the response
52+
response = json.dumps({
53+
'html_output': result.stdout,
54+
'error_output': "<b>Doxygen version "+html.escape(VERSION_STR)+"</b><pre>"+html.escape(result.stderr)+"</pre>"
55+
})
56+
57+
# Send the result to the requesting HTML page
5058
self.send_response(200)
5159
self.send_header('Content-type', 'text/html')
5260
self.end_headers()
53-
self.wfile.write(result.stdout.encode())
61+
self.wfile.write(response.encode())
5462

5563
httpd = socketserver.TCPServer(("", PORT), RequestHandler)
5664

addon/doxycommentview/index.html

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,90 @@
1212
height: 100vh;
1313
}
1414
.panel {
15+
display: flex;
1516
width: 50%;
1617
padding: 20px;
1718
box-sizing: border-box;
1819
}
20+
.line-numbers {
21+
background: #f0f0f0;
22+
padding: 10px;
23+
margin: 0px;
24+
margin-top: 2px;
25+
text-align: right;
26+
user-select: none;
27+
white-space: pre;
28+
border-right: 1px solid #ccc;
29+
font-family: monospace;
30+
font-size: 14px;
31+
line-height: 1.5;
32+
overflow: hidden;
33+
}
1934
#input {
2035
width: 100%;
2136
height: 100%;
37+
padding: 10px;
38+
margin: 0px;
2239
box-sizing: border-box;
23-
resize: none; /* Prevent resizing */
40+
resize: none;
41+
font-family: monospace;
42+
font-size: 14px;
43+
line-height: 1.5;
2444
}
2545
#output {
2646
border-left: 1px solid #ccc;
47+
display: flex;
48+
flex-direction: column;
49+
overflow: hidden;
50+
}
51+
#output-area {
52+
flex: 1;
2753
overflow: auto;
2854
}
55+
#console-area {
56+
height: 150px; /* Fixed height for the console area */
57+
border-top: 1px solid #ccc;
58+
overflow: auto;
59+
background-color: #f9f9f9; /* Light grey background for console area */
60+
padding: 10px;
61+
box-sizing: border-box;
62+
}
2963
</style>
3064
</head>
3165
<body>
3266
<div class="panel">
33-
<textarea id="input"></textarea>
67+
<div class="line-numbers" id="line-numbers">1</div>
68+
<textarea id="input" oninput="updateLineNumbers()" onscroll="syncScroll()" onkeydown="updateLineNumbers()" onkeyup="updateLineNumbers()"></textarea>
3469
</div>
3570
<div class="panel" id="output">
3671
<!-- Processed output will appear here -->
72+
<div id="output-area">
73+
<!-- Processed output will appear here -->
74+
</div>
75+
<div id="console-area">
76+
<!-- Error messages will appear here -->
77+
</div>
3778
</div>
3879
<script>
80+
function updateLineNumbers() {
81+
const textarea = document.getElementById('input');
82+
const lineNumbers = document.getElementById('line-numbers');
83+
84+
const lines = textarea.value.split('\n').length;
85+
let lineNumberString = '';
86+
for (let i = 1; i <= lines; i++) {
87+
lineNumberString += i + '\n';
88+
}
89+
90+
lineNumbers.textContent = lineNumberString;
91+
}
92+
93+
function syncScroll() {
94+
const textarea = document.getElementById('input');
95+
const lineNumbers = document.getElementById('line-numbers');
96+
lineNumbers.scrollTop = textarea.scrollTop;
97+
}
98+
3999
function processInput() {
40100
const input = document.getElementById('input').value;
41101
sessionStorage.setItem('userInput', input);
@@ -46,9 +106,10 @@
46106
},
47107
body: JSON.stringify({ input: input }),
48108
})
49-
.then(response => response.text())
109+
.then(response => response.json())
50110
.then(result => {
51-
document.getElementById('output').innerHTML = result;
111+
document.getElementById('output-area').innerHTML = result.html_output;
112+
document.getElementById('console-area').innerHTML = result.error_output;
52113
});
53114
}
54115

@@ -63,6 +124,8 @@
63124
document.getElementById('input').value = savedInput;
64125
processInput();
65126
}
127+
// Initial line numbers update
128+
updateLineNumbers();
66129
};
67130
</script>
68131
</body>

src/classdef.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,9 @@ static QCString makeQualifiedNameWithTemplateParameters(const ClassDef *cd,
7979
if (!scName.isEmpty()) scName+=scopeSeparator;
8080

8181
bool isSpecialization = cd->localName().find('<')!=-1;
82-
8382
QCString clName = cd->className();
8483
scName+=clName;
85-
if (!cd->templateArguments().empty())
84+
if (lang!=SrcLangExt::CSharp && !cd->templateArguments().empty())
8685
{
8786
if (actualParams && *actualParamIndex<actualParams->size())
8887
{
@@ -802,6 +801,7 @@ ClassDefImpl::ClassDefImpl(
802801
bool isSymbol,bool isJavaEnum)
803802
: DefinitionMixin(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),nullptr,nullptr,isSymbol)
804803
{
804+
AUTO_TRACE("name={}",name());
805805
setReference(lref);
806806
m_compType = ct;
807807
m_isJavaEnum = isJavaEnum;
@@ -853,6 +853,7 @@ ClassDefImpl::ClassDefImpl(
853853
{
854854
m_fileName = convertNameToFile(m_fileName);
855855
}
856+
AUTO_TRACE_EXIT("m_fileName='{}'",m_fileName);
856857
}
857858

858859
std::unique_ptr<ClassDef> ClassDefImpl::deepCopy(const QCString &name) const
@@ -861,6 +862,13 @@ std::unique_ptr<ClassDef> ClassDefImpl::deepCopy(const QCString &name) const
861862
auto result = std::make_unique<ClassDefImpl>(
862863
getDefFileName(),getDefLine(),getDefColumn(),name,compoundType(),
863864
std::string(),std::string(),true,m_isJavaEnum);
865+
result->setBriefDescription(briefDescription(),briefFile(),briefLine());
866+
result->setDocumentation(documentation(),docFile(),docLine());
867+
result->setInbodyDocumentation(inbodyDocumentation(),inbodyFile(),inbodyLine());
868+
result->setBodySegment(getStartDefLine(),getStartBodyLine(),getEndBodyLine());
869+
result->setBodyDef(getBodyDef());
870+
result->setLanguage(getLanguage());
871+
864872
// copy other members
865873
result->m_memberListFileName = m_memberListFileName;
866874
result->m_collabFileName = m_collabFileName;
@@ -2353,7 +2361,7 @@ void ClassDefImpl::writeTagFile(TextStream &tagFile) const
23532361
{
23542362
for (const auto &innerCd : m_innerClasses)
23552363
{
2356-
if (innerCd->isLinkableInProject() && innerCd->templateMaster()==nullptr &&
2364+
if (innerCd->isLinkableInProject() && !innerCd->isImplicitTemplateInstance() &&
23572365
protectionLevelVisible(innerCd->protection()) &&
23582366
!innerCd->isEmbeddedInOuterScope()
23592367
)
@@ -2946,6 +2954,7 @@ void ClassDefImpl::writeDocumentation(OutputList &ol) const
29462954
hli = HighlightedItem::ClassVisible;
29472955
}
29482956

2957+
AUTO_TRACE("name='{}' getOutputFileBase='{}'",name(),getOutputFileBase());
29492958
startFile(ol,getOutputFileBase(),name(),pageTitle,hli,!generateTreeView);
29502959
if (!generateTreeView)
29512960
{
@@ -3043,7 +3052,7 @@ void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const
30433052
for (const auto &innerCd : m_innerClasses)
30443053
{
30453054
if (
3046-
innerCd->isLinkableInProject() && innerCd->templateMaster()==nullptr &&
3055+
innerCd->isLinkableInProject() && !innerCd->isImplicitTemplateInstance() &&
30473056
protectionLevelVisible(innerCd->protection()) &&
30483057
!innerCd->isEmbeddedInOuterScope()
30493058
)
@@ -3534,7 +3543,7 @@ bool ClassDefImpl::isLinkableInProject() const
35343543
bool extractLocal = Config_getBool(EXTRACT_LOCAL_CLASSES);
35353544
bool extractStatic = Config_getBool(EXTRACT_STATIC);
35363545
bool hideUndoc = Config_getBool(HIDE_UNDOC_CLASSES);
3537-
if (m_templateMaster)
3546+
if (m_templateMaster && m_implicitTemplateInstance)
35383547
{
35393548
return m_templateMaster->isLinkableInProject();
35403549
}
@@ -3563,7 +3572,7 @@ bool ClassDefImpl::isLinkableInProject() const
35633572

35643573
bool ClassDefImpl::isLinkable() const
35653574
{
3566-
if (m_templateMaster)
3575+
if (m_templateMaster && m_implicitTemplateInstance)
35673576
{
35683577
return m_templateMaster->isLinkable();
35693578
}
@@ -3593,6 +3602,8 @@ bool ClassDefImpl::isVisibleInHierarchy() const
35933602
(m_templateMaster && m_templateMaster->hasDocumentation()) ||
35943603
isReference()
35953604
) &&
3605+
// if this is an implicit template instance then it most be part of the inheritance hierarchy
3606+
(!m_implicitTemplateInstance || !m_inherits.empty() || !m_inheritedBy.empty()) &&
35963607
// is not part of an unnamed namespace or shown anyway
35973608
(!m_isStatic || extractStatic);
35983609
}
@@ -4209,7 +4220,8 @@ QCString ClassDefImpl::getOutputFileBase() const
42094220
}
42104221
}
42114222
}
4212-
if (m_templateMaster)
4223+
AUTO_TRACE("name='{}' m_templateMaster={} m_implicitTemplateInstance={}",name(),(void*)m_templateMaster,m_implicitTemplateInstance);
4224+
if (m_templateMaster && m_implicitTemplateInstance)
42134225
{
42144226
// point to the template of which this class is an instance
42154227
return m_templateMaster->getOutputFileBase();
@@ -4224,7 +4236,7 @@ QCString ClassDefImpl::getInstanceOutputFileBase() const
42244236

42254237
QCString ClassDefImpl::getSourceFileBase() const
42264238
{
4227-
if (m_templateMaster)
4239+
if (m_templateMaster && m_implicitTemplateInstance)
42284240
{
42294241
return m_templateMaster->getSourceFileBase();
42304242
}
@@ -4396,7 +4408,7 @@ void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const Argumen
43964408

43974409
QCString ClassDefImpl::getReference() const
43984410
{
4399-
if (m_templateMaster)
4411+
if (m_templateMaster && m_implicitTemplateInstance)
44004412
{
44014413
return m_templateMaster->getReference();
44024414
}
@@ -4408,7 +4420,7 @@ QCString ClassDefImpl::getReference() const
44084420

44094421
bool ClassDefImpl::isReference() const
44104422
{
4411-
if (m_templateMaster)
4423+
if (m_templateMaster && m_implicitTemplateInstance)
44124424
{
44134425
return m_templateMaster->isReference();
44144426
}
@@ -4442,14 +4454,13 @@ QCString ClassDefImpl::qualifiedNameWithTemplateParameters(
44424454

44434455
QCString ClassDefImpl::className() const
44444456
{
4445-
if (m_className.isEmpty())
4446-
{
4447-
return localName();
4448-
}
4449-
else
4457+
QCString name = m_className.isEmpty() ? localName() : m_className;
4458+
auto lang = getLanguage();
4459+
if (lang==SrcLangExt::CSharp)
44504460
{
4451-
return m_className;
4461+
name = demangleCSharpGenericName(name,tempArgListToString(templateArguments(),lang));
44524462
}
4463+
return name;
44534464
}
44544465

44554466
void ClassDefImpl::setClassName(const QCString &name)
@@ -5154,7 +5165,7 @@ QCString ClassDefImpl::anchor() const
51545165
QCString anc;
51555166
if (isEmbeddedInOuterScope() && !Doxygen::generatingXmlOutput)
51565167
{
5157-
if (m_templateMaster)
5168+
if (m_templateMaster && m_implicitTemplateInstance)
51585169
{
51595170
// point to the template of which this class is an instance
51605171
anc = m_templateMaster->getOutputFileBase();

src/config.xml

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4050,11 +4050,10 @@ UML notation for the relationships.
40504050
<![CDATA[
40514051
The \c DOT_IMAGE_FORMAT tag can be used to set the image format of the images
40524052
generated by \c dot. For an explanation of the image formats see the section output formats
4053-
in the documentation of the \c dot tool
4054-
(<a href="https://www.graphviz.org/">Graphviz</a>).
4055-
\note If you choose \c svg you need to set
4056-
\ref cfg_html_file_extension "HTML_FILE_EXTENSION" to \c xhtml in order to make the SVG files
4057-
visible in IE 9+ (other browsers do not have this requirement).
4053+
in the documentation of the \c dot tool (<a href="https://www.graphviz.org/">Graphviz</a>).
4054+
<br>Note the formats `svg:cairo` and `svg:cairo:cairo` cannot be used in combination with
4055+
\ref cfg_interactive_svg "INTERACTIVE_SVG" (the \ref cfg_interactive_svg "INTERACTIVE_SVG"
4056+
will be set to `NO`).
40584057
]]>
40594058
</docs>
40604059
<value name='png'/>
@@ -4069,16 +4068,35 @@ UML notation for the relationships.
40694068
<value name='png:cairo:gdiplus'/>
40704069
<value name='png:gdiplus'/>
40714070
<value name='png:gdiplus:gdiplus'/>
4071+
<value name='svg:cairo'/>
4072+
<value name='svg:cairo:cairo'/>
4073+
<value name='svg:svg'/>
4074+
<value name='svg:svg:core'/>
4075+
<value name='gif:cairo'/>
4076+
<value name='gif:cairo:gd'/>
4077+
<value name='gif:cairo:gdiplus'/>
4078+
<value name='gif:gdiplus'/>
4079+
<value name='gif:gdiplus:gdiplus'/>
4080+
<value name='gif:gd'/>
4081+
<value name='gif:gd:gd'/>
4082+
<value name='jpg:cairo'/>
4083+
<value name='jpg:cairo:gd'/>
4084+
<value name='jpg:cairo:gdiplus'/>
4085+
<value name='jpg:gd'/>
4086+
<value name='jpg:gd:gd'/>
4087+
<value name='jpg:gdiplus'/>
4088+
<value name='jpg:gdiplus:gdiplus'/>
40724089
</option>
40734090
<option type='bool' id='INTERACTIVE_SVG' defval='0' depends='HAVE_DOT'>
40744091
<docs>
40754092
<![CDATA[
4076-
If \ref cfg_dot_image_format "DOT_IMAGE_FORMAT" is set to \c svg, then this option can be set to \c YES to
4093+
If \ref cfg_dot_image_format "DOT_IMAGE_FORMAT" is set to `svg` or `svg:svg` or `svg:svg:core`,
4094+
then this option can be set to \c YES to
40774095
enable generation of interactive SVG images that allow zooming and panning.
40784096
<br>Note that this requires a modern browser other than Internet Explorer.
40794097
Tested and working are Firefox, Chrome, Safari, and Opera.
4080-
\note For IE 9+ you need to set \ref cfg_html_file_extension "HTML_FILE_EXTENSION" to \c xhtml in order
4081-
to make the SVG files visible. Older versions of IE do not have SVG support.
4098+
<br>Note This option will be automatically disabled when \ref cfg_dot_image_format "DOT_IMAGE_FORMAT"
4099+
is set to `svg:cairo` or `svg:cairo:cairo`.
40824100
]]>
40834101
</docs>
40844102
</option>

src/configimpl.l

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,19 @@ void Config::checkAndCorrect(bool quiet, const bool check)
21892189
Config_updateInt(MAX_DOT_GRAPH_DEPTH,1000);
21902190
}
21912191

2192+
//------------------------
2193+
if (Config_getBool(INTERACTIVE_SVG))
2194+
{
2195+
// issue 11308
2196+
if ((Config_getEnum(DOT_IMAGE_FORMAT) == DOT_IMAGE_FORMAT_t::svg_cairo) ||
2197+
(Config_getEnum(DOT_IMAGE_FORMAT) == DOT_IMAGE_FORMAT_t::svg_cairo_cairo))
2198+
{
2199+
err("When using DOT_IMAGE_FORMAT with %s the %s option should be %s. I'll adjust it for you.\n",
2200+
qPrint(Config_getEnumAsString(DOT_IMAGE_FORMAT)),"INTERACTIVE_SVG","disabled");
2201+
Config_updateBool(INTERACTIVE_SVG,FALSE);
2202+
}
2203+
}
2204+
21922205
//------------------------
21932206
// check for settings that are inconsistent with having OPTIMIZED_OUTPUT_VHDL enabled
21942207
if (Config_getBool(OPTIMIZE_OUTPUT_VHDL))

0 commit comments

Comments
 (0)