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