Wt examples  3.2.2
/home/koen/project/wt/public-git/wt/examples/wt-homepage/SourceView.C
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     // 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 }

Generated on Fri Jul 27 2012 for the C++ Web Toolkit (Wt) by doxygen 1.7.5.1