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