diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmdmapper.cpp | 2 | ||||
-rw-r--r-- | src/cmdmapper.h | 4 | ||||
-rw-r--r-- | src/commentcnv.l | 6 | ||||
-rw-r--r-- | src/commentscan.l | 16 | ||||
-rw-r--r-- | src/compound.xsd | 2 | ||||
-rw-r--r-- | src/config.l | 31 | ||||
-rw-r--r-- | src/config.xml | 10 | ||||
-rw-r--r-- | src/docbookvisitor.cpp | 94 | ||||
-rw-r--r-- | src/docbookvisitor.h | 1 | ||||
-rw-r--r-- | src/docparser.cpp | 18 | ||||
-rw-r--r-- | src/docparser.h | 2 | ||||
-rw-r--r-- | src/doctokenizer.h | 1 | ||||
-rw-r--r-- | src/doctokenizer.l | 32 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 48 | ||||
-rw-r--r-- | src/htmldocvisitor.h | 1 | ||||
-rw-r--r-- | src/htmlentity.cpp | 2 | ||||
-rw-r--r-- | src/latexdocvisitor.cpp | 29 | ||||
-rw-r--r-- | src/latexdocvisitor.h | 1 | ||||
-rw-r--r-- | src/libdoxygen.pro.in | 2 | ||||
-rw-r--r-- | src/mandocvisitor.cpp | 1 | ||||
-rw-r--r-- | src/markdown.cpp | 4 | ||||
-rw-r--r-- | src/perlmodgen.cpp | 3 | ||||
-rw-r--r-- | src/plantuml.cpp | 97 | ||||
-rw-r--r-- | src/plantuml.h | 40 | ||||
-rw-r--r-- | src/printdocvisitor.h | 2 | ||||
-rw-r--r-- | src/rtfdocvisitor.cpp | 34 | ||||
-rw-r--r-- | src/rtfdocvisitor.h | 1 | ||||
-rw-r--r-- | src/xmldocvisitor.cpp | 5 |
28 files changed, 447 insertions, 42 deletions
diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index 45469f2..b0ca85f 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -120,8 +120,10 @@ CommandMap cmdMap[] = { "_internalref", CMD_INTERNALREF }, { "dot", CMD_DOT }, { "msc", CMD_MSC }, + { "startuml", CMD_STARTUML }, { "enddot", CMD_ENDDOT }, { "endmsc", CMD_ENDMSC }, + { "enduml", CMD_ENDUML }, { "manonly", CMD_MANONLY }, { "endmanonly", CMD_ENDMANONLY }, { "includelineno", CMD_INCWITHLINES }, diff --git a/src/cmdmapper.h b/src/cmdmapper.h index d89e368..75fd8ec 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -127,7 +127,9 @@ enum CommandType CMD_DIAFILE = 97, CMD_LATEXINCLUDE = 98, CMD_NDASH = 99, - CMD_MDASH = 100 + CMD_MDASH = 100, + CMD_STARTUML = 101, + CMD_ENDUML = 102 }; enum HtmlTagType diff --git a/src/commentcnv.l b/src/commentcnv.l index 4cc9da9..ec56b90 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -446,7 +446,7 @@ void replaceComment(int offset); g_blockName=&yytext[1]; BEGIN(VerbatimCode); } -<CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */ +<CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */ copyToOutput(yytext,(int)yyleng); g_lastCommentContext = YY_START; g_javaBlock=0; @@ -517,7 +517,7 @@ void replaceComment(int offset); } } } -<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */ +<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */ copyToOutput(yytext,(int)yyleng); if (&yytext[4]==g_blockName) { @@ -554,7 +554,7 @@ void replaceComment(int offset); copyToOutput(yytext,(int)yyleng); } <Verbatim>^[ \t]*"///" { - if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f') + if (g_blockName=="dot" || g_blockName=="msc" || g_blockName=="startuml" || g_blockName.at(0)=='f') { // see bug 487871, strip /// from dot images and formulas. int l=0; diff --git a/src/commentscan.l b/src/commentscan.l index a42f6ce..369349b 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -191,6 +191,7 @@ static DocCmdMap docCmdMap[] = { "manonly", &handleFormatBlock, FALSE }, { "dot", &handleFormatBlock, TRUE }, { "msc", &handleFormatBlock, TRUE }, + { "startuml", &handleFormatBlock, TRUE }, { "code", &handleFormatBlock, TRUE }, { "addindex", &handleAddIndex, FALSE }, { "if", &handleIf, FALSE }, @@ -877,7 +878,7 @@ static int yyread(char *buf,int max_size) /* start command character */ CMD ("\\"|"@") DCMD1 ("arg"|"attention"|"author"|"cite"|"code") -DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example") +DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example"|"startuml") DCMD3 ("htmlinclude"|"htmlonly"|"image"|"include") DCMD4 ("includelineno"|"internal"|"invariant") DCMD5 ("latexinclude"|"latexonly"|"li"|"line"|"manonly"|"name") @@ -1785,6 +1786,13 @@ RCSTAG "$"{ID}":"[^\n$]+"$" BEGIN(Comment); } } +<FormatBlock>{CMD}"enduml" { + addOutput(yytext); + if (blockName=="startuml") // found end of the block + { + BEGIN(Comment); + } + } <FormatBlock>[^ \@\*\/\\\n]* { // some word addOutput(yytext); } @@ -1809,9 +1817,11 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput(*yytext); } <FormatBlock><<EOF>> { + QCString endTag = "@end"+blockName; + if (blockName=="startuml") endTag="enduml"; warn(yyFileName,yyLineNr, - "reached end of comment while inside a @%s block; check for missing @end%s tag!", - blockName.data(),blockName.data() + "reached end of comment while inside a @%s block; check for missing @%s tag!", + blockName.data(),endTag.data() ); yyterminate(); } diff --git a/src/compound.xsd b/src/compound.xsd index dec596b..be897c3 100644 --- a/src/compound.xsd +++ b/src/compound.xsd @@ -386,7 +386,7 @@ <xsd:element name="rtfonly" type="xsd:string" /> <xsd:element name="latexonly" type="xsd:string" /> <xsd:element name="dot" type="xsd:string" /> - <xsd:element name="msc" type="xsd:string" /> + <xsd:element name="plantuml" type="xsd:string" /> <xsd:element name="anchor" type="docAnchorType" /> <xsd:element name="formula" type="docFormulaType" /> <xsd:element name="ref" type="docRefTextType" /> diff --git a/src/config.l b/src/config.l index 133bc11..a237faf 100644 --- a/src/config.l +++ b/src/config.l @@ -1329,6 +1329,37 @@ void Config::check() mscgenPath=""; } + // check plantuml path + QCString &plantumlJarPath = Config_getString("PLANTUML_JAR_PATH"); + if (!plantumlJarPath.isEmpty()) + { + QFileInfo pu(plantumlJarPath); + if (pu.exists() && pu.isDir()) // PLANTUML_JAR_PATH is directory + { + QFileInfo jar(plantumlJarPath+portable_pathSeparator()+"plantuml.jar"); + if (jar.exists() && jar.isFile()) + { + plantumlJarPath = jar.dirPath(TRUE).utf8()+portable_pathSeparator(); + } + else + { + config_err("Jar file plantuml.jar not found at location " + "specified via PLANTUML_JAR_PATH: '%s'\n",plantumlJarPath.data()); + plantumlJarPath=""; + } + } + else if (pu.exists() && pu.isFile() && plantumlJarPath.right(4)==".jar") // PLANTUML_JAR_PATH is file + { + plantumlJarPath = pu.dirPath(TRUE).utf8()+portable_pathSeparator(); + } + else + { + config_err("path specified via PLANTUML_JAR_PATH does not exist or not a directory: %s\n", + plantumlJarPath.data()); + plantumlJarPath=""; + } + } + // check dia path QCString &diaPath = Config_getString("DIA_PATH"); if (!diaPath.isEmpty()) diff --git a/src/config.xml b/src/config.xml index 5a0af59..9020d30 100644 --- a/src/config.xml +++ b/src/config.xml @@ -3295,6 +3295,16 @@ to be found in the default search path. ]]> </docs> </option> + <option type='string' id='PLANTUML_JAR_PATH' format='dir' defval='' depends='HAVE_DOT'> + <docs> +<![CDATA[ + When using plantuml, the \c PLANTUML_JAR_PATH tag should be used to specify the path where + java can find the \c plantuml.jar file. If left blank, it is assumed PlantUML is not used or + called during a preprocessing step. Doxygen will generate a warning when it encounters a + \ref cmdstartuml "\\startuml" command in this case and will not generate output for the diagram. +]]> + </docs> + </option> <option type='int' id='DOT_GRAPH_MAX_NODES' minval='0' maxval='10000' defval='50' depends='HAVE_DOT'> <docs> <![CDATA[ diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 5d7aafd..9f2dbe3 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -34,6 +34,7 @@ #include "msc.h" #include "dia.h" #include "htmlentity.h" +#include "plantuml.h" DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci) : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) @@ -216,35 +217,58 @@ void DocbookDocVisitor::visit(DocVerbatim *s) } break; case DocVerbatim::Msc: - static int mscindex = 1; - QCString baseName(4096); - QCString name; - QCString stext = s->text(); - m_t << "<para>" << endl; - name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex); - baseName.sprintf("%s%d", - (Config_getString("DOCBOOK_OUTPUT")+"/inline_mscgraph_").data(), - mscindex++ - ); - QFile file(baseName+".msc"); - if (!file.open(IO_WriteOnly)) { - err("Could not open file %s.msc for writing\n",baseName.data()); + static int mscindex = 1; + QCString baseName(4096); + QCString name; + QCString stext = s->text(); + m_t << "<para>" << endl; + name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex); + baseName.sprintf("%s%d", + (Config_getString("DOCBOOK_OUTPUT")+"/inline_mscgraph_").data(), + mscindex++ + ); + QFile file(baseName+".msc"); + if (!file.open(IO_WriteOnly)) + { + err("Could not open file %s.msc for writing\n",baseName.data()); + } + QCString text = "msc {"; + text+=stext; + text+="}"; + file.writeBlock( text, text.length() ); + file.close(); + m_t << " <figure>" << endl; + m_t << " <title>" << name << "</title>" << endl; + m_t << " <mediaobject>" << endl; + m_t << " <imageobject>" << endl; + writeMscFile(baseName); + m_t << " </imageobject>" << endl; + m_t << " </mediaobject>" << endl; + m_t << " </figure>" << endl; + m_t << "</para>" << endl; + } + break; + case DocVerbatim::PlantUML: + { + static QCString docbookOutput = Config_getString("DOCBOOK_OUTPUT"); + QCString baseName = writePlantUMLSource(docbookOutput,s->exampleFile(),s->text()); + QCString shortName = baseName; + int i; + if ((i=shortName.findRev('/'))!=-1) + { + shortName=shortName.right(shortName.length()-i-1); + } + m_t << " <figure>" << endl; + m_t << " <title>" << shortName << "</title>" << endl; + m_t << " <mediaobject>" << endl; + m_t << " <imageobject>" << endl; + writePlantUMLFile(baseName); + m_t << " </imageobject>" << endl; + m_t << " </mediaobject>" << endl; + m_t << " </figure>" << endl; + m_t << "</para>" << endl; } - QCString text = "msc {"; - text+=stext; - text+="}"; - file.writeBlock( text, text.length() ); - file.close(); - m_t << " <figure>" << endl; - m_t << " <title>" << name << "</title>" << endl; - m_t << " <mediaobject>" << endl; - m_t << " <imageobject>" << endl; - writeMscFile(baseName); - m_t << " </imageobject>" << endl; - m_t << " </mediaobject>" << endl; - m_t << " </figure>" << endl; - m_t << "</para>" << endl; break; } } @@ -1195,6 +1219,22 @@ void DocbookDocVisitor::writeMscFile(const QCString &baseName) m_t << "</imagedata>" << endl; } +void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName) +{ + QCString shortName = baseName; + int i; + if ((i=shortName.findRev('/'))!=-1) + { + shortName=shortName.right(shortName.length()-i-1); + } + QCString outDir = Config_getString("DOCBOOK_OUTPUT"); + generatePlantUMLOutput(baseName,outDir,PUML_BITMAP); + m_t << " <imagedata"; + m_t << " width=\"50%\""; + m_t << " align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << shortName << ".png" << "\">"; + m_t << "</imagedata>" << endl; +} + void DocbookDocVisitor::startMscFile(const QCString &fileName, const QCString &width, const QCString &height, diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index 20d424e..dd67aba 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -156,6 +156,7 @@ class DocbookDocVisitor : public DocVisitor const QCString &height, bool hasCaption); void endDotFile(bool hasCaption); void writeDotFile(const QCString &fileName); + void writePlantUMLFile(const QCString &fileName); //-------------------------------------- // state variables //-------------------------------------- diff --git a/src/docparser.cpp b/src/docparser.cpp index 6d788fd..bab0c75 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -5569,6 +5569,23 @@ int DocPara::handleCommand(const QCString &cmdName) doctokenizerYYsetStatePara(); } break; + case CMD_STARTUML: + { + static QCString jarPath = Config_getString("PLANTUML_JAR_PATH"); + doctokenizerYYsetStatePlantUML(); + retval = doctokenizerYYlex(); + if (jarPath.isEmpty()) + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring startuml command because PLANTUML_JAR_PATH is not set"); + } + else + { + m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::PlantUML,FALSE,g_token->sectionId)); + } + if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker"); + doctokenizerYYsetStatePara(); + } + break; case CMD_ENDPARBLOCK: retval=RetVal_EndParBlock; break; @@ -5583,6 +5600,7 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_ENDVERBATIM: case CMD_ENDDOT: case CMD_ENDMSC: + case CMD_ENDUML: warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); break; case CMD_PARAM: diff --git a/src/docparser.h b/src/docparser.h index 17f296b..3dc3d84 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -433,7 +433,7 @@ class DocWhiteSpace : public DocNode class DocVerbatim : public DocNode { public: - enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly }; + enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML }; DocVerbatim(DocNode *parent,const QCString &context, const QCString &text, Type t,bool isExample, const QCString &exampleFile,bool isBlock=FALSE,const QCString &lang=QCString()); diff --git a/src/doctokenizer.h b/src/doctokenizer.h index 1db764e..c95230b 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -160,5 +160,6 @@ void doctokenizerYYpushBackHtmlTag(const char *tag); void doctokenizerYYsetStateSnippet(); void doctokenizerYYstartAutoList(); void doctokenizerYYendAutoList(); +void doctokenizerYYsetStatePlantUML(); #endif diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 3bd2058..ea4a1a4 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -417,6 +417,8 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} %x St_Verbatim %x St_Dot %x St_Msc +%x St_PlantUMLOpt +%x St_PlantUML %x St_Param %x St_XRefItem %x St_XRefItem2 @@ -843,7 +845,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} <St_Dot>. { /* dot text */ g_token->verb+=yytext; } -<St_Msc>{CMD}("endmsc"|"endvhdlflow") { +<St_Msc>{CMD}("endmsc") { return RetVal_OK; } <St_Msc>[^\\@\n]+ | @@ -851,6 +853,23 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} <St_Msc>. { /* msc text */ g_token->verb+=yytext; } +<St_PlantUMLOpt>\n { + g_token->sectionId=g_token->sectionId.stripWhiteSpace(); + BEGIN(St_PlantUML); + } +<St_PlantUMLOpt>["{}] { // skip curly brackets or quotes around the optional image name + } +<St_PlantUMLOpt>. { + g_token->sectionId += yytext; + } +<St_PlantUML>{CMD}"enduml" { + return RetVal_OK; + } +<St_PlantUML>[^\\@\n]+ | +<St_PlantUML>\n | +<St_PlantUML>. { /* plantuml text */ + g_token->verb+=yytext; + } <St_Title>"\"" { // quoted title BEGIN(St_TitleQ); } @@ -1121,6 +1140,10 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} g_endMarker="endmsc"; BEGIN(St_SecSkip); } +<St_Sections>{CMD}"startuml"/[^a-z_A-Z0-9] { + g_endMarker="enduml"; + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] { g_endMarker="endhtmlonly"; BEGIN(St_SecSkip); @@ -1318,6 +1341,13 @@ void doctokenizerYYsetStateMsc() BEGIN(St_Msc); } +void doctokenizerYYsetStatePlantUML() +{ + g_token->verb=""; + g_token->sectionId=""; + BEGIN(St_PlantUMLOpt); +} + void doctokenizerYYsetStateParam() { BEGIN(St_Param); diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index bd94232..e319a1f 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -34,6 +34,7 @@ #include "filedef.h" #include "memberdef.h" #include "htmlentity.h" +#include "plantuml.h" static const int NUM_HTML_LIST_TYPES = 4; static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"}; @@ -429,9 +430,21 @@ void HtmlDocVisitor::visit(DocVerbatim *s) m_t << "<div align=\"center\">" << endl; writeMscFile(baseName+".msc",s->relPath(),s->context()); if (Config_getBool("DOT_CLEANUP")) file.remove(); + m_t << "</div>" << endl; + forceStartParagraph(s); + } + break; + case DocVerbatim::PlantUML: + { + forceEndParagraph(s); + + static QCString htmlOutput = Config_getString("HTML_OUTPUT"); + QCString baseName = writePlantUMLSource(htmlOutput,s->exampleFile(),s->text()); + m_t << "<div align=\"center\">" << endl; + writePlantUMLFile(baseName,s->relPath(),s->context()); + m_t << "</div>" << endl; + forceStartParagraph(s); } - m_t << "</div>" << endl; - forceStartParagraph(s); break; } } @@ -1976,6 +1989,37 @@ void HtmlDocVisitor::writeDiaFile(const QCString &fileName, m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl; } +void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, + const QCString &relPath, + const QCString &) +{ + QCString baseName=fileName; + int i; + if ((i=baseName.findRev('/'))!=-1) // strip path + { + baseName=baseName.right(baseName.length()-i-1); + } + if ((i=baseName.findRev('.'))!=-1) // strip extension + { + baseName=baseName.left(i); + } + static QCString outDir = Config_getString("HTML_OUTPUT"); + static QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); + if (imgExt=="svg") + { + generatePlantUMLOutput(fileName,outDir,PUML_SVG); + //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />" << endl; + //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; + //m_t << "</iframe>" << endl; + m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>" << endl; + } + else + { + generatePlantUMLOutput(fileName,outDir,PUML_BITMAP); + m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl; + } +} + /** Used for items found inside a paragraph, which due to XHTML restrictions * have to be outside of the paragraph. This method will forcefully end * the current paragraph and forceStartParagraph() will restart it. diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h index ddefecd..00ae09e 100644 --- a/src/htmldocvisitor.h +++ b/src/htmldocvisitor.h @@ -153,6 +153,7 @@ class HtmlDocVisitor : public DocVisitor void writeDotFile(const QCString &fileName,const QCString &relPath,const QCString &context); void writeMscFile(const QCString &fileName,const QCString &relPath,const QCString &context); void writeDiaFile(const QCString &fileName,const QCString &relPath,const QCString &context); + void writePlantUMLFile(const QCString &fileName,const QCString &relPath,const QCString &context); void pushEnabled(); void popEnabled(); diff --git a/src/htmlentity.cpp b/src/htmlentity.cpp index c49491e..216b65c 100644 --- a/src/htmlentity.cpp +++ b/src/htmlentity.cpp @@ -462,7 +462,7 @@ const DocSymbol::PerlSymb *HtmlEntityMapper::perl(DocSymbol::SymType symb) const /*! * @brief Give code of the requested HTML entity name - * @param symName HTML entity name without \c & and \c; + * @param symName HTML entity name without \c & and \c ; * @return the code for the requested HTML entity name, * in case the requested HTML item does not exist `DocSymbol::Sym_unknown` is returned. */ diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index dd23d60..af1a5fd 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -32,6 +32,7 @@ #include "filedef.h" #include "config.h" #include "htmlentity.h" +#include "plantuml.h" static QCString escapeLabelName(const char *s) { @@ -321,6 +322,16 @@ void LatexDocVisitor::visit(DocVerbatim *s) if (Config_getBool("DOT_CLEANUP")) file.remove(); } break; + case DocVerbatim::PlantUML: + { + QCString latexOutput = Config_getString("LATEX_OUTPUT"); + QCString baseName = writePlantUMLSource(latexOutput,s->exampleFile(),s->text()); + + m_t << "\\begin{center}\n"; + writePlantUMLFile(baseName); + m_t << "\\end{center}\n"; + } + break; } } @@ -1743,6 +1754,7 @@ void LatexDocVisitor::writeMscFile(const QCString &baseName) m_t << "\\end{DoxyImageNoCaption}\n"; } + void LatexDocVisitor::startDiaFile(const QCString &fileName, const QCString &width, const QCString &height, @@ -1834,3 +1846,20 @@ void LatexDocVisitor::writeDiaFile(const QCString &baseName) m_t << "\\end{DoxyImageNoCaption}\n"; } +void LatexDocVisitor::writePlantUMLFile(const QCString &baseName) +{ + QCString shortName = baseName; + int i; + if ((i=shortName.findRev('/'))!=-1) + { + shortName=shortName.right(shortName.length()-i-1); + } + QCString outDir = Config_getString("LATEX_OUTPUT"); + generatePlantUMLOutput(baseName,outDir,PUML_EPS); + m_t << "\n\\begin{DoxyImageNoCaption}" + " \\mbox{\\includegraphics"; + m_t << "{" << shortName << "}"; + m_t << "}\n"; // end mbox + m_t << "\\end{DoxyImageNoCaption}\n"; +} + diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index d386569..64560b9 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -176,6 +176,7 @@ class LatexDocVisitor : public DocVisitor const QCString &height, bool hasCaption); void endDiaFile(bool hasCaption); void writeDiaFile(const QCString &fileName); + void writePlantUMLFile(const QCString &fileName); void pushEnabled(); void popEnabled(); diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in index f50f987..703b885 100644 --- a/src/libdoxygen.pro.in +++ b/src/libdoxygen.pro.in @@ -87,6 +87,7 @@ HEADERS = arguments.h \ pagedef.h \ perlmodgen.h \ lodepng.h \ + plantuml.h \ pre.h \ printdocvisitor.h \ pycode.h \ @@ -165,6 +166,7 @@ SOURCES = arguments.cpp \ layout.cpp \ lodepng.cpp \ logos.cpp \ + plantuml.cpp \ mandocvisitor.cpp \ mangen.cpp \ sqlite3gen.cpp \ diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index 5403324..1fe5409 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -208,6 +208,7 @@ void ManDocVisitor::visit(DocVerbatim *s) case DocVerbatim::DocbookOnly: case DocVerbatim::Dot: case DocVerbatim::Msc: + case DocVerbatim::PlantUML: /* nothing */ break; } diff --git a/src/markdown.cpp b/src/markdown.cpp index 291e1dc..11b01ea 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -208,6 +208,10 @@ static QCString isBlockCommand(const char *data,int offset,int size) { return "end"+blockName; } + else if (blockName=="startuml") + { + return "enduml"; + } else if (blockName=="f" && end<size) { if (data[end]=='$') diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 948836b..c636cdf 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -662,8 +662,9 @@ void PerlModDocVisitor::visit(DocVerbatim *s) case DocVerbatim::LatexOnly: type = "latexonly"; break; case DocVerbatim::XmlOnly: type = "xmlonly"; break; case DocVerbatim::DocbookOnly: type = "docbookonly"; break; - case DocVerbatim::Dot: type = "dot"; break; + case DocVerbatim::Dot: type = "dot"; break; case DocVerbatim::Msc: type = "msc"; break; + case DocVerbatim::PlantUML: type = "plantuml"; break; } openItem(type); m_output.addFieldQuotedString("content", s->text()); diff --git a/src/plantuml.cpp b/src/plantuml.cpp new file mode 100644 index 0000000..18f028b --- /dev/null +++ b/src/plantuml.cpp @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2014 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include "plantuml.h" +#include "portable.h" +#include "config.h" +#include "message.h" + +#include <qdir.h> + +//static const int maxCmdLine = 40960; + +QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content) +{ + QCString baseName(4096); + static int umlindex=1; + + if (fileName.isEmpty()) // generate name + { + baseName = outDir+"/inline_umlgraph_"+QCString().setNum(umlindex++); + } + else // user specified name + { + baseName = fileName; + int i=baseName.findRev('.'); + if (i!=-1) baseName = baseName.left(i); + baseName.prepend(outDir+"/"); + } + QFile file(baseName+".pu"); + if (!file.open(IO_WriteOnly)) + { + err("Could not open file %s for writing\n",baseName.data()); + } + QCString text = "@startuml\n"; + text+=content; + text+="@enduml\n"; + file.writeBlock( text, text.length() ); + file.close(); + return baseName; +} + +void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format) +{ + static QCString plantumlJarPath = Config_getString("PLANTUML_JAR_PATH"); + + QCString pumlExe = "java"; + QCString pumlArgs = "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" "; + pumlArgs+="-o \""; + pumlArgs+=outDir; + pumlArgs+="\" "; + QCString extension; + switch (format) + { + case PUML_BITMAP: + pumlArgs+="-tpng"; + extension=".png"; + break; + case PUML_EPS: + pumlArgs+="-teps"; + extension=".eps"; + break; + case PUML_SVG: + pumlArgs+="-tsvg"; + extension=".svg"; + break; + } + pumlArgs+=" \""; + pumlArgs+=baseName; + pumlArgs+=".pu\" "; + int exitCode; + //printf("*** running: %s %s outDir:%s %s\n",pumlExe.data(),pumlArgs.data(),outDir,outFile); + msg("Running PlantUML on generated file %s.pu\n",baseName); + portable_sysTimerStart(); + if ((exitCode=portable_system(pumlExe,pumlArgs,FALSE))!=0) + { + err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line\n", + plantumlJarPath.data()); + } + else if (Config_getBool("DOT_CLEANUP")) + { + QFile(QCString(baseName)+".pu").remove(); + } + portable_sysTimerStop(); +} + diff --git a/src/plantuml.h b/src/plantuml.h new file mode 100644 index 0000000..27626d1 --- /dev/null +++ b/src/plantuml.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2014 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef PLANTUML_H +#define PLANTUML_H + +class QCString; + +/** Plant UML output image formats */ +enum PlantUMLOutputFormat { PUML_BITMAP, PUML_EPS, PUML_SVG }; + +/** Write a PlantUML compatible file. + * @param[in] outDir the output directory to write the file to. + * @param[in] fileName the name of the file. If empty a name will be chosen automatically. + * @param[in] content the contents of the PlantUML file. + * @returns The name of the generated file. + */ +QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content); + +/** Convert a PlantUML file to an image. + * @param[in] baseName the name of the generated file (as returned by writePlantUMLSource()) + * @param[in] outDir the directory to write the resulting image into. + * @param[in] format the image format to generate. + */ +void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format); + +#endif + diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index ee2ae3f..1d384b1 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -134,6 +134,7 @@ class PrintDocVisitor : public DocVisitor case DocVerbatim::DocbookOnly: printf("<docbookonly>"); break; case DocVerbatim::Dot: printf("<dot>"); break; case DocVerbatim::Msc: printf("<msc>"); break; + case DocVerbatim::PlantUML: printf("<plantuml>"); break; } printf("%s",s->text().data()); switch(s->type()) @@ -148,6 +149,7 @@ class PrintDocVisitor : public DocVisitor case DocVerbatim::DocbookOnly: printf("</docbookonly>"); break; case DocVerbatim::Dot: printf("</dot>"); break; case DocVerbatim::Msc: printf("</msc>"); break; + case DocVerbatim::PlantUML: printf("</plantuml>"); break; } } void visit(DocAnchor *a) diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 0d17208..5e27137 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -16,6 +16,8 @@ * */ +#include <qfileinfo.h> + #include "rtfdocvisitor.h" #include "docparser.h" #include "language.h" @@ -26,13 +28,13 @@ #include "util.h" #include "rtfstyle.h" #include "message.h" -#include <qfileinfo.h> #include "parserintf.h" #include "msc.h" #include "dia.h" #include "filedef.h" #include "config.h" #include "htmlentity.h" +#include "plantuml.h" //#define DBG_RTF(x) m_t << x #define DBG_RTF(x) do {} while(0) @@ -317,6 +319,16 @@ void RTFDocVisitor::visit(DocVerbatim *s) if (Config_getBool("DOT_CLEANUP")) file.remove(); } break; + case DocVerbatim::PlantUML: + { + static QCString rtfOutput = Config_getString("RTF_OUTPUT"); + QCString baseName = writePlantUMLSource(rtfOutput,s->exampleFile(),s->text()); + + m_t << "\\par{\\qc "; // center picture + writePlantUMLFile(baseName); + m_t << "} "; + } + break; } m_lastIsPara=FALSE; } @@ -1704,3 +1716,23 @@ void RTFDocVisitor::writeDiaFile(const QCString &fileName) m_lastIsPara=TRUE; } +void RTFDocVisitor::writePlantUMLFile(const QCString &fileName) +{ + QCString baseName=fileName; + int i; + if ((i=baseName.findRev('/'))!=-1) + { + baseName=baseName.right(baseName.length()-i-1); + } + QCString outDir = Config_getString("RTF_OUTPUT"); + generatePlantUMLOutput(fileName,outDir,PUML_BITMAP); + if (!m_lastIsPara) m_t << "\\par" << endl; + m_t << "{" << endl; + m_t << rtf_Style_Reset; + m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; + m_t << baseName << ".png"; + m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; + m_t << "}" << endl; + m_lastIsPara=TRUE; +} + diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h index efc9d21..c50802d 100644 --- a/src/rtfdocvisitor.h +++ b/src/rtfdocvisitor.h @@ -155,6 +155,7 @@ class RTFDocVisitor : public DocVisitor void writeDotFile(const QCString &fileName); void writeMscFile(const QCString &fileName); void writeDiaFile(const QCString &fileName); + void writePlantUMLFile(const QCString &fileName); //-------------------------------------- // state variables diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 343926c..f2da28c 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -209,6 +209,11 @@ void XmlDocVisitor::visit(DocVerbatim *s) filter(s->text()); m_t << "</msc>"; break; + case DocVerbatim::PlantUML: + m_t << "<plantuml>"; + filter(s->text()); + m_t << "</plantuml>"; + break; } } |