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