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, ".css"))
00074 return "css";
00075 else
00076 return std::string();
00077 }
00078
00079 std::string readFileToString(const std::string &fileName)
00080 {
00081 std::size_t outputFileSize = fs::file_size(fileName);
00082 std::fstream file (fileName.c_str(), std::ios::in | std::ios::binary);
00083 char* memblock = new char [outputFileSize];
00084 file.read(memblock, outputFileSize);
00085 file.close();
00086 std::string data = std::string(memblock, outputFileSize);
00087 delete [] memblock;
00088 return data;
00089 }
00090
00091 WWidget * SourceView::renderView()
00092 {
00093 if (!index_.isValid()) {
00094
00095 WText *result = new WText();
00096 result->setInline(false);
00097 return result;
00098 }
00099
00100
00101
00102
00103 boost::any contentsData = index_.data(contentRole_);
00104 std::string content;
00105 if (!contentsData.empty())
00106 content = boost::any_cast<const std::string&>(contentsData);
00107 boost::any fileNameData = index_.data(fileNameRole_);
00108 std::string fileName =
00109 boost::any_cast<const std::string&>(fileNameData);
00110 boost::any filePathData = index_.data(filePathRole_);
00111 std::string filePath;
00112 if (!filePathData.empty())
00113 filePath = boost::any_cast<const std::string&>(filePathData);
00114
00115
00116
00117
00118 std::string lang = getLanguageFromFileExtension(fileName);
00119 if (content != "" && content.substr(0, 100).find("-*- C++ -*-")
00120 != std::string::npos)
00121 lang = "cpp";
00122
00123 std::string outputFileName;
00124
00125 if (lang != "") {
00126 std::string inputFileName;
00127
00128 if (!filePathData.empty())
00129 inputFileName = filePath;
00130 else {
00131 inputFileName = tempFileName();
00132 std::ofstream out(inputFileName.c_str(),
00133 std::ios::out | std::ios::binary);
00134 out.write(content.c_str(), content.length());
00135 out.close();
00136 }
00137
00138 outputFileName = tempFileName();
00139
00140 std::string sourceHighlightCommand = "source-highlight ";
00141 sourceHighlightCommand += "--src-lang=" + lang + " ";
00142 sourceHighlightCommand += "--out-format=xhtml ";
00143 sourceHighlightCommand += "--input=" + inputFileName + " ";
00144 sourceHighlightCommand += "--output=" + outputFileName + " ";
00145
00146 std::cerr << sourceHighlightCommand << std::endl;
00147 bool sourceHighlightOk = system(sourceHighlightCommand.c_str()) == 0;
00148
00149 if (sourceHighlightOk)
00150 content = readFileToString(outputFileName);
00151 else {
00152 content = readFileToString(inputFileName);
00153 lang = "";
00154 }
00155 unlink(outputFileName.c_str());
00156
00157 if (filePathData.empty())
00158 unlink(inputFileName.c_str());
00159 }
00160
00161 if (content == "")
00162
00163
00164 if (!boost::iends_with(fileName, ".jar")
00165 && !boost::iends_with(fileName, ".war")
00166 && !boost::iends_with(fileName, ".class"))
00167 content = readFileToString(fileName);
00168
00169 delete imageResource_;
00170 imageResource_ = 0;
00171
00172 WWidget *result = 0;
00173
00174 if (!imageExtension(fileName).empty()) {
00175 WImage *image = new WImage();
00176 imageResource_ = new WMemoryResource(this);
00177 imageResource_->setMimeType("mime/" + imageExtension(fileName));
00178 imageResource_->setData((const unsigned char*)content.data(),
00179 content.length());
00180 image->setResource(imageResource_);
00181 result = image;
00182 } else if (lang != "") {
00183 WText *text = new WText();
00184 text->setTextFormat(XHTMLUnsafeText);
00185 text->setText(content);
00186 result = text;
00187 } else {
00188 WText *text = new WText();
00189 text->setTextFormat(PlainText);
00190 text->setText(content);
00191 result = text;
00192 }
00193
00194 result->setInline(false);
00195 WApplication::instance()
00196 ->doJavaScript(result->jsRef() + ".parentNode.scrollTop = 0;");
00197 return result;
00198 }
00199
00200 std::string SourceView::imageExtension(const std::string& fileName)
00201 {
00202 static const char *imageExtensions[] = {
00203 ".png", ".gif", ".jpg", "jpeg", ".ico", 0
00204 };
00205
00206 fs::path p(fileName);
00207 std::string extension = fs::extension(p);
00208
00209 for (const char **s = imageExtensions; *s != 0; ++s)
00210 if (*s == extension)
00211 return extension.substr(1);
00212
00213 return std::string();
00214 }