Wt examples
3.2.3
|
00001 #include "SourceView.h" 00002 00003 #include <iostream> 00004 #include <fstream> 00005 #include <sstream> 00006 00007 #include <stdlib.h> 00008 00009 #include <boost/algorithm/string.hpp> 00010 #include <boost/filesystem/operations.hpp> 00011 #include <boost/filesystem/convenience.hpp> 00012 00013 #include <Wt/WApplication> 00014 #include <Wt/WText> 00015 #include <Wt/WImage> 00016 00017 using namespace Wt; 00018 namespace fs = boost::filesystem; 00019 00020 SourceView::SourceView(int fileNameRole, int contentRole, int filePathRole) 00021 : fileNameRole_(fileNameRole), 00022 contentRole_(contentRole), 00023 filePathRole_(filePathRole), 00024 imageResource_(0) 00025 {} 00026 00027 SourceView::~SourceView() 00028 { } 00029 00030 bool SourceView::setIndex(const WModelIndex& index) 00031 { 00032 if (index != index_ && index.isValid()) { 00033 std::string fp = index.data(filePathRole_).empty() ? std::string() 00034 : boost::any_cast<std::string>(index.data(filePathRole_)); 00035 00036 if (!index.data(contentRole_).empty() 00037 || (!fp.empty() && !fs::is_directory(fp))) { 00038 index_ = index; 00039 update(); 00040 00041 return true; 00042 } 00043 } 00044 00045 return false; 00046 } 00047 00048 std::string tempFileName() 00049 { 00050 #ifndef WIN32 00051 char spool[20]; 00052 strcpy(spool, "/tmp/wtXXXXXX"); 00053 00054 int i = mkstemp(spool); 00055 close(i); 00056 #else 00057 char spool[2 * L_tmpnam]; 00058 tmpnam(spool); 00059 #endif 00060 return std::string(spool); 00061 } 00062 00063 std::string getLanguageFromFileExtension(const std::string &fileName) 00064 { 00065 if (boost::iends_with(fileName, ".h") 00066 || boost::iends_with(fileName, ".C") 00067 || boost::iends_with(fileName, ".cpp")) 00068 return "cpp"; 00069 else if (boost::iends_with(fileName, ".xml")) 00070 return "xml"; 00071 else if (boost::iends_with(fileName, ".html")) 00072 return "html"; 00073 else if (boost::iends_with(fileName, ".java")) 00074 return "java"; 00075 else if (boost::iends_with(fileName, ".js")) 00076 return "javascript"; 00077 else if (boost::iends_with(fileName, ".css")) 00078 return "css"; 00079 else 00080 return std::string(); 00081 } 00082 00083 std::string readFileToString(const std::string& fileName) 00084 { 00085 std::size_t outputFileSize = (std::size_t)fs::file_size(fileName); 00086 std::fstream file (fileName.c_str(), std::ios::in | std::ios::binary); 00087 char* memblock = new char [outputFileSize]; 00088 file.read(memblock, (std::streamsize)outputFileSize); 00089 file.close(); 00090 std::string data = std::string(memblock, outputFileSize); 00091 delete [] memblock; 00092 return data; 00093 } 00094 00095 WWidget * SourceView::renderView() 00096 { 00097 if (!index_.isValid()) { 00098 // no content 00099 WText *result = new WText(); 00100 result->setInline(false); 00101 return result; 00102 } 00103 00104 /* 00105 * read the contents, from string or file name 00106 */ 00107 boost::any contentsData = index_.data(contentRole_); 00108 std::string content; 00109 if (!contentsData.empty()) 00110 content = boost::any_cast<const std::string&>(contentsData); 00111 boost::any fileNameData = index_.data(fileNameRole_); 00112 std::string fileName = 00113 boost::any_cast<const std::string&>(fileNameData); 00114 boost::any filePathData = index_.data(filePathRole_); 00115 std::string filePath; 00116 if (!filePathData.empty()) 00117 filePath = boost::any_cast<const std::string&>(filePathData); 00118 00119 /* 00120 * determine source language, for source highlight 00121 */ 00122 std::string lang = getLanguageFromFileExtension(fileName); 00123 if (content != "" && content.substr(0, 100).find("-*- C++ -*-") 00124 != std::string::npos) 00125 lang = "cpp"; 00126 00127 std::string outputFileName; 00128 00129 if (lang != "") { 00130 std::string inputFileName; 00131 00132 if (!filePathData.empty()) 00133 inputFileName = filePath; 00134 else { 00135 inputFileName = tempFileName(); 00136 std::ofstream out(inputFileName.c_str(), 00137 std::ios::out | std::ios::binary); 00138 out.write(content.c_str(), (std::streamsize)content.length()); 00139 out.close(); 00140 } 00141 00142 outputFileName = tempFileName(); 00143 00144 std::string sourceHighlightCommand = "source-highlight "; 00145 sourceHighlightCommand += "--src-lang=" + lang + " "; 00146 sourceHighlightCommand += "--out-format=xhtml "; 00147 sourceHighlightCommand += "--input=" + inputFileName + " "; 00148 sourceHighlightCommand += "--output=" + outputFileName + " "; 00149 00150 std::cerr << sourceHighlightCommand << std::endl; 00151 bool sourceHighlightOk = system(sourceHighlightCommand.c_str()) == 0; 00152 00153 if (sourceHighlightOk) 00154 content = readFileToString(outputFileName); 00155 else { 00156 content = readFileToString(inputFileName); 00157 lang = ""; 00158 } 00159 unlink(outputFileName.c_str()); 00160 00161 if (filePathData.empty()) 00162 unlink(inputFileName.c_str()); 00163 } 00164 00165 if (content == "") 00166 // do not load binary files, we would need to perform proper UTF-8 00167 // transcoding to display them 00168 if (!boost::iends_with(fileName, ".jar") 00169 && !boost::iends_with(fileName, ".war") 00170 && !boost::iends_with(fileName, ".class")) 00171 content = readFileToString(fileName); 00172 00173 delete imageResource_; 00174 imageResource_ = 0; 00175 00176 WWidget *result = 0; 00177 00178 if (!imageExtension(fileName).empty()) { 00179 WImage *image = new WImage(); 00180 imageResource_ = new WMemoryResource(this); 00181 imageResource_->setMimeType("mime/" + imageExtension(fileName)); 00182 imageResource_->setData((const unsigned char*)content.data(), 00183 (int)content.length()); 00184 image->setImageLink(imageResource_); 00185 result = image; 00186 } else if (lang != "") { 00187 WText *text = new WText(); 00188 text->setTextFormat(XHTMLUnsafeText); 00189 text->setText(WString::fromUTF8(content)); 00190 result = text; 00191 } else { 00192 WText *text = new WText(); 00193 text->setTextFormat(PlainText); 00194 text->setText(WString::fromUTF8(content)); 00195 result = text; 00196 } 00197 00198 result->setInline(false); 00199 WApplication::instance() 00200 ->doJavaScript(result->jsRef() + ".parentNode.scrollTop = 0;"); 00201 return result; 00202 } 00203 00204 std::string SourceView::imageExtension(const std::string& fileName) 00205 { 00206 static const char *imageExtensions[] = { 00207 ".png", ".gif", ".jpg", "jpeg", ".ico", 0 00208 }; 00209 00210 fs::path p(fileName); 00211 std::string extension = fs::extension(p); 00212 00213 for (const char **s = imageExtensions; *s != 0; ++s) 00214 if (*s == extension) 00215 return extension.substr(1); 00216 00217 return std::string(); 00218 }