Go to the documentation of this file.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
00099 WText *result = new WText();
00100 result->setInline(false);
00101 return result;
00102 }
00103
00104
00105
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
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
00167
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->setResource(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 }