Doxygen
plantuml.cpp
浏览该文件的文档.
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 
16 #include "plantuml.h"
17 #include "util.h"
18 #include "portable.h"
19 #include "config.h"
20 #include "doxygen.h"
21 #include "message.h"
22 #include "debug.h"
23 #include "fileinfo.h"
24 #include "dir.h"
25 
27  const QCString &content,OutputFormat format, const QCString &engine,
28  const QCString &srcFile,int srcLine)
29 {
30  QCString baseName;
31  QCString puName;
32  QCString imgName;
33  QCString outDir(outDirArg);
34  static int umlindex=1;
35 
36  Debug::print(Debug::Plantuml,0,"*** %s fileName: %s\n","writePlantUMLSource",qPrint(fileName));
37  Debug::print(Debug::Plantuml,0,"*** %s outDir: %s\n","writePlantUMLSource",qPrint(outDir));
38 
39  // strip any trailing slashes and backslashes
40  uint l;
41  while ((l=outDir.length())>0 && (outDir.at(l-1)=='/' || outDir.at(l-1)=='\\'))
42  {
43  outDir = outDir.left(l-1);
44  }
45 
46  if (fileName.isEmpty()) // generate name
47  {
48  puName = "inline_umlgraph_"+QCString().setNum(umlindex);
49  baseName = outDir+"/inline_umlgraph_"+QCString().setNum(umlindex++);
50  }
51  else // user specified name
52  {
53  baseName = fileName;
54  int i=baseName.findRev('.');
55  if (i!=-1) baseName = baseName.left(i);
56  puName = baseName;
57  baseName.prepend(outDir+"/");
58  }
59 
60  switch (format)
61  {
62  case PUML_BITMAP:
63  imgName =puName+".png";
64  break;
65  case PUML_EPS:
66  imgName =puName+".eps";
67  break;
68  case PUML_SVG:
69  imgName =puName+".svg";
70  break;
71  }
72 
73  Debug::print(Debug::Plantuml,0,"*** %s baseName: %s\n","writePlantUMLSource",qPrint(baseName));
74  Debug::print(Debug::Plantuml,0,"*** %s puName: %s\n","writePlantUMLSource",qPrint(puName));
75  Debug::print(Debug::Plantuml,0,"*** %s imgName: %s\n","writePlantUMLSource",qPrint(imgName));
76 
77  QCString text = "@start"+engine+" "+imgName+"\n";
78  text+=content;
79  text+="\n@end"+engine+"\n";
80 
81  QCString qcOutDir(outDir);
82  uint pos = qcOutDir.findRev("/");
83  QCString generateType(qcOutDir.right(qcOutDir.length() - (pos + 1)) );
84  Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n","writePlantUMLSource",qPrint(generateType));
85  PlantumlManager::instance().insert(generateType.str(),puName.str(),outDir,format,text,srcFile,srcLine);
86  Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n","writePlantUMLSource",qPrint(generateType));
87 
88  return baseName;
89 }
90 
91 void PlantumlManager::generatePlantUMLOutput(const QCString &baseName,const QCString &outDir,OutputFormat format)
92 {
93  QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH);
94  QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE);
95  QCString dotPath = Config_getString(DOT_PATH);
96 
97  QCString imgName = baseName;
98  // The basename contains path, we need to strip the path from the filename in order
99  // to create the image file name which should be included in the index.qhp (Qt help index file).
100  int i;
101  if ((i=imgName.findRev('/'))!=-1) // strip path
102  {
103  imgName=imgName.right(imgName.length()-i-1);
104  }
105  switch (format)
106  {
107  case PUML_BITMAP:
108  imgName+=".png";
109  break;
110  case PUML_EPS:
111  imgName+=".eps";
112  break;
113  case PUML_SVG:
114  imgName+=".svg";
115  break;
116  }
117 
119 }
120 
121 //--------------------------------------------------------------------
122 
123 
125 {
126  static PlantumlManager theInstance;
127  return theInstance;
128 }
129 
131 {
132 }
133 
134 static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles,
135  const PlantumlManager::ContentMap &plantumlContent,
137 {
138  /* example : running: java -Djava.awt.headless=true
139  -jar "/usr/local/bin/plantuml.jar"
140  -o "test_doxygen/DOXYGEN_OUTPUT/html"
141  -tpng
142  "test_doxygen/DOXYGEN_OUTPUT/html/A.pu"
143  -charset UTF-8
144  outDir:test_doxygen/DOXYGEN_OUTPUT/html
145  test_doxygen/DOXYGEN_OUTPUT/html/A
146  */
147  int exitCode;
148  QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH);
149  QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE);
150  QCString dotPath = Config_getString(DOT_PATH);
151 
152  QCString pumlExe = "java";
153  QCString pumlArgs = "";
154  QCString pumlType = "";
155  QCString pumlOutDir = "";
156 
157  const StringVector &pumlIncludePathList = Config_getList(PLANTUML_INCLUDE_PATH);
158  {
159  auto it = pumlIncludePathList.begin();
160  if (it!=pumlIncludePathList.end())
161  {
162  pumlArgs += "-Dplantuml.include.path=\"";
163  pumlArgs += it->c_str();
164  ++it;
165  }
166  while (it!=pumlIncludePathList.end())
167  {
168  pumlArgs += Portable::pathListSeparator();
169  pumlArgs += it->c_str();
170  ++it;
171  }
172  }
173  if (!pumlIncludePathList.empty()) pumlArgs += "\" ";
174  pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" ";
175  if (!plantumlConfigFile.isEmpty())
176  {
177  pumlArgs += "-config \"";
178  pumlArgs += plantumlConfigFile;
179  pumlArgs += "\" ";
180  }
181  if (Config_getBool(HAVE_DOT) && !dotPath.isEmpty())
182  {
183  pumlArgs += "-graphvizdot \"";
184  pumlArgs += dotPath;
185  pumlArgs += "dot";
186  pumlArgs += Portable::commandExtension();
187  pumlArgs += "\" ";
188  }
189  switch (format)
190  {
192  pumlType="png";
193  break;
195  pumlType="eps";
196  break;
198  pumlType="svg";
199  break;
200  }
201 
202  {
203  for (const auto &kv : plantumlContent)
204  {
205  const PlantumlContent &nb = kv.second;
206  if (nb.content.isEmpty()) continue;
207 
208  QCString pumlArguments = pumlArgs;
209  msg("Generating PlantUML %s Files in %s\n",qPrint(pumlType),kv.first.c_str());
210  pumlArguments+="-o \"";
211  pumlArguments+=nb.outDir;
212  pumlArguments+="\" ";
213  pumlArguments+="-charset UTF-8 -t";
214  pumlArguments+=pumlType;
215  pumlArguments+=" ";
216 
217  QCString puFileName("");
218  puFileName+=nb.outDir;
219  puFileName+="/";
220  pumlOutDir=puFileName;
221  puFileName+="inline_umlgraph_";
222  puFileName+=pumlType;
223  puFileName+=kv.first.c_str();
224  puFileName+=".pu";
225 
226  pumlArguments+="\"";
227  pumlArguments+=puFileName;
228  pumlArguments+="\" ";
229 
230 
231  QCString cachedContent;
232  FileInfo fi(puFileName.str());
233  if (fi.exists())
234  {
235  cachedContent = fileToString(puFileName);
236  }
237 
238  std::ofstream file(puFileName.str(),std::ofstream::out | std::ofstream::binary);
239  if (!file.is_open())
240  {
241  err_full(nb.srcFile,nb.srcLine,"Could not open file %s for writing\n",puFileName.data());
242  }
243  file.write( nb.content.data(), nb.content.length() );
244  file.close();
245  Debug::print(Debug::Plantuml,0,"*** %s Running Plantuml arguments:%s\n","PlantumlManager::runPlantumlContent",qPrint(pumlArguments));
246 
247  if (cachedContent == nb.content) continue;
248 
250  if ((exitCode=Portable::system(pumlExe.data(),pumlArguments.data(),TRUE))!=0)
251  {
252  err_full(nb.srcFile,nb.srcLine,"Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n",
253  plantumlJarPath.data(),exitCode);
254  }
256 
257  if ( (format==PlantumlManager::PUML_EPS) && (Config_getBool(USE_PDFLATEX)) )
258  {
259  Debug::print(Debug::Plantuml,0,"*** %s Running epstopdf\n","PlantumlManager::runPlantumlContent");
260  auto files_kv = plantumlFiles.find(kv.first);
261  if (files_kv!=plantumlFiles.end())
262  {
263  for (const auto &str : files_kv->second)
264  {
265  const int maxCmdLine = 40960;
266  QCString epstopdfArgs(maxCmdLine);
267  epstopdfArgs.sprintf("\"%s%s.eps\" --outfile=\"%s%s.pdf\"",
268  pumlOutDir.data(),str.c_str(), pumlOutDir.data(),str.c_str());
270  if ((exitCode=Portable::system("epstopdf",epstopdfArgs.data()))!=0)
271  {
272  err_full(nb.srcFile,nb.srcLine,"Problems running epstopdf. Check your TeX installation! Exit code: %d\n",exitCode);
273  }
275  }
276  }
277  }
278  }
279  }
280 }
281 
283 {
284  Debug::print(Debug::Plantuml,0,"*** %s\n","PlantumlManager::run");
288 }
289 
290 static void print(const PlantumlManager::FilesMap &plantumlFiles)
291 {
293  {
294  for (const auto &kv : plantumlFiles)
295  {
296  Debug::print(Debug::Plantuml,0,"*** %s PlantumlFiles key:%s size:%zu\n","PlantumlManager::print Files",kv.first.c_str(),kv.second.size());
297  for (const auto &s : kv.second)
298  {
299  Debug::print(Debug::Plantuml,0,"*** %s list:%s\n","PlantumlManager::print",s.c_str());
300  }
301  }
302  }
303 }
304 
305 static void print(const PlantumlManager::ContentMap &plantumlContent)
306 {
308  {
309  for (const auto &kv : plantumlContent)
310  {
311  Debug::print(Debug::Plantuml,0,"*** %s PlantumlContent key: %s\n","PlantumlManager::print Content",kv.first.c_str());
312  Debug::print(Debug::Plantuml,0,"*** %s Content:\n%s\n","PlantumlManager::print",kv.second.content.data());
313  }
314  }
315 }
316 
317 static void addPlantumlFiles(PlantumlManager::FilesMap &plantumlFiles,
318  const std::string &key, const std::string &value)
319 {
320  auto kv = plantumlFiles.find(key);
321  if (kv==plantumlFiles.end())
322  {
323  kv = plantumlFiles.insert(std::make_pair(key,StringVector())).first;
324  }
325  kv->second.push_back(value);
326 }
327 
328 static void addPlantumlContent(PlantumlManager::ContentMap &plantumlContent,
329  const std::string &key, const QCString &outDir, const QCString &puContent,
330  const QCString &srcFile,int srcLine)
331 {
332  auto kv = plantumlContent.find(key);
333  if (kv==plantumlContent.end())
334  {
335  kv = plantumlContent.insert(std::make_pair(key,PlantumlContent("",outDir,srcFile,srcLine))).first;
336  }
337  kv->second.content+=puContent;
338 }
339 
340 void PlantumlManager::insert(const std::string &key, const std::string &value,
341  const QCString &outDir,OutputFormat format,const QCString &puContent,
342  const QCString &srcFile,int srcLine)
343 {
344  Debug::print(Debug::Plantuml,0,"*** %s key:%s ,value:%s\n","PlantumlManager::insert",qPrint(key),qPrint(value));
345 
346  switch (format)
347  {
348  case PUML_BITMAP:
351  addPlantumlContent(m_pngPlantumlContent,key,outDir,puContent,srcFile,srcLine);
353  break;
354  case PUML_EPS:
357  addPlantumlContent(m_epsPlantumlContent,key,outDir,puContent,srcFile,srcLine);
359  break;
360  case PUML_SVG:
363  addPlantumlContent(m_svgPlantumlContent,key,outDir,puContent,srcFile,srcLine);
365  break;
366  }
367 }
368 
369 //--------------------------------------------------------------------
QCString::QCString
QCString()=default
PlantumlManager::m_epsPlantumlContent
ContentMap m_epsPlantumlContent
Definition: plantuml.h:90
PlantumlManager::writePlantUMLSource
QCString writePlantUMLSource(const QCString &outDir, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &engine, const QCString &srcFile, int srcLine)
Write a PlantUML compatible file.
Definition: plantuml.cpp:26
StringVector
std::vector< std::string > StringVector
Definition: containers.h:32
runPlantumlContent
static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles, const PlantumlManager::ContentMap &plantumlContent, PlantumlManager::OutputFormat format)
Definition: plantuml.cpp:134
fileinfo.h
maxCmdLine
static const int maxCmdLine
Definition: dia.cpp:24
PlantumlManager::PlantumlManager
PlantumlManager()
Definition: plantuml.cpp:130
QCString::length
uint length() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:147
PlantumlManager::m_epsPlantumlFiles
FilesMap m_epsPlantumlFiles
Definition: plantuml.h:87
PlantumlManager::OutputFormat
OutputFormat
Plant UML output image formats
Definition: plantuml.h:44
QCString::findRev
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition: qcstring.cpp:86
QCString::isEmpty
bool isEmpty() const
Returns TRUE iff the string is empty
Definition: qcstring.h:144
PlantumlManager::m_pngPlantumlFiles
FilesMap m_pngPlantumlFiles
Definition: plantuml.h:85
Doxygen::indexList
static IndexList * indexList
Definition: doxygen.h:114
PlantumlManager::ContentMap
std::map< std::string, PlantumlContent > ContentMap
Definition: plantuml.h:74
QCString::str
std::string str() const
Definition: qcstring.h:442
PlantumlManager::instance
static PlantumlManager & instance()
Definition: plantuml.cpp:124
QCString::at
char & at(size_t i)
Returns a reference to the character at index i.
Definition: qcstring.h:477
addPlantumlContent
static void addPlantumlContent(PlantumlManager::ContentMap &plantumlContent, const std::string &key, const QCString &outDir, const QCString &puContent, const QCString &srcFile, int srcLine)
Definition: plantuml.cpp:328
PlantumlManager::m_pngPlantumlContent
ContentMap m_pngPlantumlContent
Definition: plantuml.h:88
Debug::isFlagSet
static bool isFlagSet(DebugMask mask)
Definition: debug.cpp:99
PlantumlManager::m_svgPlantumlContent
ContentMap m_svgPlantumlContent
Definition: plantuml.h:89
PlantumlManager::m_svgPlantumlFiles
FilesMap m_svgPlantumlFiles
Definition: plantuml.h:86
uint
unsigned uint
Definition: qcstring.h:40
PlantumlManager::PUML_BITMAP
@ PUML_BITMAP
Definition: plantuml.h:44
FileInfo::exists
bool exists() const
Definition: fileinfo.cpp:30
QCString::left
QCString left(size_t len) const
Definition: qcstring.h:212
message.h
Portable::sysTimerStart
void sysTimerStart()
Definition: portable.cpp:470
IndexList::addImageFile
void addImageFile(const QCString &name)
Definition: index.h:105
PlantumlContent::outDir
QCString outDir
Definition: plantuml.h:34
PlantumlManager::insert
void insert(const std::string &key, const std::string &value, const QCString &outDir, OutputFormat format, const QCString &puContent, const QCString &srcFile, int srcLine)
Definition: plantuml.cpp:340
addPlantumlFiles
static void addPlantumlFiles(PlantumlManager::FilesMap &plantumlFiles, const std::string &key, const std::string &value)
Definition: plantuml.cpp:317
Debug::print
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition: debug.cpp:57
doxygen.h
PlantumlManager::FilesMap
std::map< std::string, StringVector > FilesMap
Definition: plantuml.h:73
PlantumlManager
Singleton that manages plantuml relation actions
Definition: plantuml.h:40
PlantumlManager::run
void run()
Run plant UML tool for all images
Definition: plantuml.cpp:282
fileToString
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition: util.cpp:1394
print
static void print(const PlantumlManager::FilesMap &plantumlFiles)
Definition: plantuml.cpp:290
TRUE
#define TRUE
Definition: qcstring.h:36
Portable::system
int system(const QCString &command, const QCString &args, bool commandHasConsole=true)
Definition: portable.cpp:42
Portable::pathListSeparator
QCString pathListSeparator()
Definition: portable.cpp:356
Config_getBool
#define Config_getBool(name)
Definition: config.h:33
msg
void msg(const char *fmt,...)
Definition: message.cpp:53
PlantumlManager::PUML_EPS
@ PUML_EPS
Definition: plantuml.h:44
FileInfo
Minimal replacement for QFileInfo.
Definition: fileinfo.h:22
PlantumlContent
Definition: plantuml.h:29
qPrint
const char * qPrint(const char *s)
Definition: qcstring.h:589
PlantumlContent::srcFile
QCString srcFile
Definition: plantuml.h:35
Config_getString
#define Config_getString(name)
Definition: config.h:32
PlantumlContent::srcLine
int srcLine
Definition: plantuml.h:36
config.h
err_full
void err_full(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:212
Portable::sysTimerStop
void sysTimerStop()
Definition: portable.cpp:475
PlantumlContent::content
QCString content
Definition: plantuml.h:33
QCString::data
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string
Definition: qcstring.h:153
plantuml.h
PlantumlManager::PUML_SVG
@ PUML_SVG
Definition: plantuml.h:44
Portable::commandExtension
const char * commandExtension()
Definition: portable.cpp:434
portable.h
Portable versions of functions that are platform dependent.
PlantumlManager::generatePlantUMLOutput
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition: plantuml.cpp:91
Debug::Plantuml
@ Plantuml
Definition: debug.h:40
dir.h
util.h
A bunch of utility functions.
QCString::right
QCString right(size_t len) const
Definition: qcstring.h:217
QCString::prepend
QCString & prepend(const char *s)
Definition: qcstring.h:339
QCString::sprintf
QCString & sprintf(const char *format,...)
Definition: qcstring.cpp:24
debug.h
Config_getList
#define Config_getList(name)
Definition: config.h:37
QCString
This is an alternative implementation of QCString.
Definition: qcstring.h:108