Wt examples  3.7.1
SourceView.C
Go to the documentation of this file.
1 #include "SourceView.h"
2 
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 
7 #include <stdlib.h>
8 
9 #include <boost/algorithm/string.hpp>
10 #include <boost/filesystem/operations.hpp>
11 #include <boost/filesystem/convenience.hpp>
12 
13 #include <Wt/WApplication>
14 #include <Wt/WText>
15 #include <Wt/WImage>
16 
17 using namespace Wt;
18 namespace fs = boost::filesystem;
19 
20 SourceView::SourceView(int fileNameRole, int contentRole, int filePathRole)
21  : fileNameRole_(fileNameRole),
22  contentRole_(contentRole),
23  filePathRole_(filePathRole),
24  imageResource_(0)
25 {}
26 
28 { }
29 
30 bool SourceView::setIndex(const WModelIndex& index)
31 {
32  if (index != index_ && index.isValid()) {
33  std::string fp = index.data(filePathRole_).empty() ? std::string()
34  : boost::any_cast<std::string>(index.data(filePathRole_));
35 
36  if (!index.data(contentRole_).empty()
37  || (!fp.empty() && !fs::is_directory(fp))) {
38  index_ = index;
39  update();
40 
41  return true;
42  }
43  }
44 
45  return false;
46 }
47 
48 std::string tempFileName()
49 {
50 #ifndef WT_WIN32
51  char spool[20];
52  strcpy(spool, "/tmp/wtXXXXXX");
53 
54  int i = mkstemp(spool);
55  close(i);
56 #else
57  char spool[2 * L_tmpnam];
58  tmpnam(spool);
59 #endif
60  return std::string(spool);
61 }
62 
63 std::string getLanguageFromFileExtension(const std::string &fileName)
64 {
65  if (boost::iends_with(fileName, ".h")
66  || boost::iends_with(fileName, ".C")
67  || boost::iends_with(fileName, ".cpp"))
68  return "cpp";
69  else if (boost::iends_with(fileName, ".xml"))
70  return "xml";
71  else if (boost::iends_with(fileName, ".html"))
72  return "html";
73  else if (boost::iends_with(fileName, ".java"))
74  return "java";
75  else if (boost::iends_with(fileName, ".js"))
76  return "javascript";
77  else if (boost::iends_with(fileName, ".css"))
78  return "css";
79  else
80  return std::string();
81 }
82 
83 std::string readFileToString(const std::string& fileName)
84 {
85  std::size_t outputFileSize = (std::size_t)fs::file_size(fileName);
86  std::fstream file (fileName.c_str(), std::ios::in | std::ios::binary);
87  char* memblock = new char [outputFileSize];
88  file.read(memblock, (std::streamsize)outputFileSize);
89  file.close();
90  std::string data = std::string(memblock, outputFileSize);
91  delete [] memblock;
92  return data;
93 }
94 
96 {
97  if (!index_.isValid()) {
98  // no content
99  WText *result = new WText();
100  result->setInline(false);
101  return result;
102  }
103 
104  /*
105  * read the contents, from string or file name
106  */
107  boost::any contentsData = index_.data(contentRole_);
108  std::string content;
109  if (!contentsData.empty())
110  content = boost::any_cast<const std::string&>(contentsData);
111  boost::any fileNameData = index_.data(fileNameRole_);
112  std::string fileName =
113  boost::any_cast<const std::string&>(fileNameData);
114  boost::any filePathData = index_.data(filePathRole_);
115  std::string filePath;
116  if (!filePathData.empty())
117  filePath = boost::any_cast<const std::string&>(filePathData);
118 
119  /*
120  * determine source language, for source highlight
121  */
122  std::string lang = getLanguageFromFileExtension(fileName);
123  if (content != "" && content.substr(0, 100).find("-*- C++ -*-")
124  != std::string::npos)
125  lang = "cpp";
126 
127  std::string outputFileName;
128 
129  if (lang != "") {
130  std::string inputFileName;
131 
132  if (!filePathData.empty())
133  inputFileName = filePath;
134  else {
135  inputFileName = tempFileName();
136  std::ofstream out(inputFileName.c_str(),
137  std::ios::out | std::ios::binary);
138  out.write(content.c_str(), (std::streamsize)content.length());
139  out.close();
140  }
141 
142  outputFileName = tempFileName();
143 
144  std::string sourceHighlightCommand = "source-highlight ";
145  sourceHighlightCommand += "--src-lang=" + lang + " ";
146  sourceHighlightCommand += "--out-format=xhtml ";
147  sourceHighlightCommand += "--input=" + inputFileName + " ";
148  sourceHighlightCommand += "--output=" + outputFileName + " ";
149 
150  std::cerr << sourceHighlightCommand << std::endl;
151  bool sourceHighlightOk = system(sourceHighlightCommand.c_str()) == 0;
152 
153  if (sourceHighlightOk)
154  content = readFileToString(outputFileName);
155  else {
156  content = readFileToString(inputFileName);
157  lang = "";
158  }
159  unlink(outputFileName.c_str());
160 
161  if (filePathData.empty())
162  unlink(inputFileName.c_str());
163  }
164 
165  if (content == "")
166  // do not load binary files, we would need to perform proper UTF-8
167  // transcoding to display them
168  if (!boost::iends_with(fileName, ".jar")
169  && !boost::iends_with(fileName, ".war")
170  && !boost::iends_with(fileName, ".class"))
171  content = readFileToString(fileName);
172 
173  delete imageResource_;
174  imageResource_ = 0;
175 
176  WWidget *result = 0;
177 
178  if (!imageExtension(fileName).empty()) {
179  WImage *image = new WImage();
180  imageResource_ = new WMemoryResource(this);
181  imageResource_->setMimeType("mime/" + imageExtension(fileName));
182  imageResource_->setData((const unsigned char*)content.data(),
183  (int)content.length());
185  result = image;
186  } else if (lang != "") {
187  WText *text = new WText();
188  text->setTextFormat(XHTMLUnsafeText);
189  text->setText(WString::fromUTF8(content));
190  result = text;
191  } else {
192  WText *text = new WText();
193  text->setTextFormat(PlainText);
194  text->setText(WString::fromUTF8(content));
195  result = text;
196  }
197 
198  result->setInline(false);
199  WApplication::instance()
200  ->doJavaScript(result->jsRef() + ".parentNode.scrollTop = 0;");
201  return result;
202 }
203 
204 std::string SourceView::imageExtension(const std::string& fileName)
205 {
206  static const char *imageExtensions[] = {
207  ".png", ".gif", ".jpg", "jpeg", ".ico", 0
208  };
209 
210  fs::path p(fileName);
211  std::string extension = fs::extension(p);
212 
213  for (const char **s = imageExtensions; *s != 0; ++s)
214  if (*s == extension)
215  return extension.substr(1);
216 
217  return std::string();
218 }
bool isValid() const
std::string jsRef() const
cpp17::any data(ItemDataRole role=ItemDataRole::Display) const
int contentRole_
Definition: SourceView.h:61
int fileNameRole_
The role that is currently displayed.
Definition: SourceView.h:60
SourceView(int fileNameRole, int contentRole, int filePathRole)
Constructor.
Definition: SourceView.C:20
bool setText(const WString &text)
bool setTextFormat(TextFormat format)
int filePathRole_
Definition: SourceView.h:62
void setMimeType(const std::string &mimeType)
std::string readFileToString(const std::string &fileName)
Definition: SourceView.C:83
void setData(const std::vector< unsigned char > &data)
std::string imageExtension(const std::string &fileName)
Definition: SourceView.C:204
virtual void setInline(bool inlined)=0
void setImageLink(const WLink &link)
Wt::WMemoryResource * imageResource_
Definition: SourceView.h:64
bool setIndex(const Wt::WModelIndex &index)
Sets the model index.
Definition: SourceView.C:30
std::string getLanguageFromFileExtension(const std::string &fileName)
Definition: SourceView.C:63
virtual Wt::WWidget * renderView()
Returns the widget that renders the view.
Definition: SourceView.C:95
Wt::WModelIndex index_
The index that is currently displayed.
Definition: SourceView.h:57
virtual void setInline(bool isInline) override
std::string tempFileName()
Definition: SourceView.C:48
virtual ~SourceView()
Destructor.
Definition: SourceView.C:27

Generated on Tue Dec 15 2020 for the C++ Web Toolkit (Wt) by doxygen 1.8.13