00001
00002
00003
00004
00005
00006
00007 #include <fstream>
00008 #include <iostream>
00009
00010 #include <boost/lexical_cast.hpp>
00011 #include <boost/tokenizer.hpp>
00012 #include <boost/algorithm/string.hpp>
00013
00014 #include <Wt/WAnchor>
00015 #include <Wt/WApplication>
00016 #include <Wt/WEnvironment>
00017 #include <Wt/WLogger>
00018 #include <Wt/WMenu>
00019 #include <Wt/WStackedWidget>
00020 #include <Wt/WVBoxLayout>
00021 #include <Wt/WTabWidget>
00022 #include <Wt/WTable>
00023 #include <Wt/WTableCell>
00024 #include <Wt/WText>
00025 #include <Wt/WViewWidget>
00026
00027 #include "Home.h"
00028 #include "view/BlogView.h"
00029
00030 static const std::string SRC_INTERNAL_PATH = "src";
00031
00032
00033 class Div : public WContainerWidget
00034 {
00035 public:
00036 Div(WContainerWidget *parent, const std::string& id)
00037 : WContainerWidget(parent)
00038 {
00039 setId(id);
00040 }
00041 };
00042
00043 Home::~Home()
00044 {
00045 }
00046
00047 Home::Home(const WEnvironment& env, const std::string& title,
00048 const std::string& resourceBundle, const std::string& cssPath)
00049 : WApplication(env),
00050 releases_(0),
00051 homePage_(0),
00052 sourceViewer_(0)
00053 {
00054 messageResourceBundle().use(appRoot() + resourceBundle, false);
00055 useStyleSheet(cssPath + "/wt.css");
00056 useStyleSheet(cssPath + "/wt_ie.css", "lt IE 7");
00057 useStyleSheet("css/home.css");
00058 useStyleSheet("css/sourceview.css");
00059 setTitle(title);
00060
00061 setLocale("");
00062 language_ = 0;
00063 }
00064
00065 void Home::init()
00066 {
00067 internalPathChanged().connect(this, &Home::setup);
00068 internalPathChanged().connect(this, &Home::setLanguageFromPath);
00069 internalPathChanged().connect(this, &Home::logInternalPath);
00070
00071 setup();
00072
00073 setLanguageFromPath();
00074 }
00075
00076 void Home::setup()
00077 {
00078
00079
00080
00081
00082
00083
00084 std::string base = internalPathNextPart("/");
00085
00086 if (base == SRC_INTERNAL_PATH) {
00087 if (!sourceViewer_) {
00088 delete homePage_;
00089 homePage_ = 0;
00090
00091 root()->clear();
00092
00093 sourceViewer_ = sourceViewer("/" + SRC_INTERNAL_PATH + "/");
00094 WVBoxLayout *layout = new WVBoxLayout();
00095 layout->setContentsMargins(0, 0, 0, 0);
00096 layout->addWidget(sourceViewer_);
00097 root()->setLayout(layout);
00098 }
00099 } else {
00100 if (!homePage_) {
00101 delete sourceViewer_;
00102 sourceViewer_ = 0;
00103
00104 root()->clear();
00105
00106 homePage_ = initHome();
00107 root()->addWidget(homePage_);
00108 }
00109 }
00110 }
00111
00112 WWidget *Home::initHome()
00113 {
00114 WContainerWidget *result = new WContainerWidget(root());
00115 Div *topWrapper = new Div(result, "top_wrapper");
00116 Div *topContent = new Div(topWrapper, "top_content");
00117
00118 Div *languagesDiv = new Div(topContent, "top_languages");
00119
00120 for (unsigned i = 0; i < languages.size(); ++i) {
00121 if (i != 0)
00122 new WText("- ", languagesDiv);
00123
00124 const Lang& l = languages[i];
00125
00126 WAnchor *a = new WAnchor("", WString::fromUTF8(l.longDescription_),
00127 languagesDiv);
00128 a->setRefInternalPath(l.path_);
00129 }
00130
00131 WText *topWt = new WText(tr("top_wt"), topContent);
00132 topWt->setInline(false);
00133 topWt->setId("top_wt");
00134
00135 WText *bannerWt = new WText(tr("banner_wrapper"), result);
00136 bannerWt->setId("banner_wrapper");
00137
00138 Div *mainWrapper = new Div(result, "main_wrapper");
00139 Div *mainContent = new Div(mainWrapper, "main_content");
00140 Div *mainMenu = new Div(mainContent, "main_menu");
00141
00142 WStackedWidget *contents = new WStackedWidget();
00143 contents->setId("main_page");
00144
00145 mainMenu_ = new WMenu(contents, Vertical, mainMenu);
00146 mainMenu_->setRenderAsList(true);
00147
00148 mainMenu_->addItem
00149 (tr("introduction"), introduction())->setPathComponent("");
00150
00151 mainMenu_->addItem
00152 (tr("blog"), deferCreate(boost::bind(&Home::blog, this)));
00153
00154 mainMenu_->addItem
00155 (tr("features"), wrapView(&Home::features), WMenuItem::PreLoading);
00156
00157 mainMenu_->addItem
00158 (tr("documentation"), wrapView(&Home::documentation),
00159 WMenuItem::PreLoading);
00160
00161 mainMenu_->addItem
00162 (tr("examples"), examples(),
00163 WMenuItem::PreLoading)->setPathComponent("examples/");
00164
00165 mainMenu_->addItem
00166 (tr("download"), deferCreate(boost::bind(&Home::download, this)),
00167 WMenuItem::PreLoading);
00168
00169 mainMenu_->addItem
00170 (tr("community"), wrapView(&Home::community), WMenuItem::PreLoading);
00171
00172 mainMenu_->addItem
00173 (tr("other-language"), wrapView(&Home::otherLanguage),
00174 WMenuItem::PreLoading);
00175
00176 mainMenu_->itemSelectRendered().connect(this, &Home::updateTitle);
00177
00178 mainMenu_->itemSelected().connect(this, &Home::googleAnalyticsLogger);
00179
00180
00181 mainMenu_->setInternalPathEnabled("/");
00182
00183 sideBarContent_ = new WContainerWidget(mainMenu);
00184
00185 mainContent->addWidget(contents);
00186 WContainerWidget *clearAll = new WContainerWidget(mainContent);
00187 clearAll->setStyleClass("clearall");
00188
00189 WText *footerWrapper = new WText(tr("footer_wrapper"), result);
00190 footerWrapper->setId("footer_wrapper");
00191
00192 return result;
00193 }
00194
00195 void Home::setLanguage(int index)
00196 {
00197 if (homePage_) {
00198 const Lang& l = languages[index];
00199
00200 setLocale(l.code_);
00201
00202 std::string langPath = l.path_;
00203 mainMenu_->setInternalBasePath(langPath);
00204 examplesMenu_->setInternalBasePath(langPath + "examples");
00205 updateTitle();
00206
00207 language_ = index;
00208 }
00209 }
00210
00211 WWidget *Home::linkSourceBrowser(const std::string& example)
00212 {
00213 WAnchor *a = new WAnchor("", tr("source-browser"));
00214 a->setRefInternalPath("/" + SRC_INTERNAL_PATH + "/" + example);
00215 return a;
00216 }
00217
00218 void Home::setLanguageFromPath()
00219 {
00220 std::string langPath = internalPathNextPart("/");
00221
00222 if (langPath.empty())
00223 langPath = '/';
00224 else
00225 langPath = '/' + langPath + '/';
00226
00227 int newLanguage = 0;
00228
00229 for (unsigned i = 0; i < languages.size(); ++i) {
00230 if (languages[i].path_ == langPath) {
00231 newLanguage = i;
00232 break;
00233 }
00234 }
00235
00236 if (newLanguage != language_)
00237 setLanguage(newLanguage);
00238 }
00239
00240 void Home::updateTitle()
00241 {
00242 if (mainMenu_->currentItem()) {
00243 setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
00244 }
00245 }
00246
00247 void Home::logInternalPath(const std::string& path)
00248 {
00249
00250 log("path") << path;
00251
00252
00253 if (path.size() >= 4 && path.substr(0, 4) == "/src") {
00254 googleAnalyticsLogger();
00255 }
00256 }
00257
00258 WWidget *Home::introduction()
00259 {
00260 return new WText(tr("home.intro"));
00261 }
00262
00263 WWidget *Home::blog()
00264 {
00265 return new BlogView("/blog/", appRoot() + "blog.db", "/wt/blog/feed/");
00266 }
00267
00268 WWidget *Home::status()
00269 {
00270 return new WText(tr("home.status"));
00271 }
00272
00273 WWidget *Home::features()
00274 {
00275 return new WText(tr("home.features"));
00276 }
00277
00278 WWidget *Home::documentation()
00279 {
00280 return new WText(tr("home.documentation"));
00281 }
00282
00283 WWidget *Home::otherLanguage()
00284 {
00285 return new WText(tr("home.other-language"));
00286 }
00287
00288 WWidget *Home::wrapView(WWidget *(Home::*createWidget)())
00289 {
00290 return makeStaticModel(boost::bind(createWidget, this));
00291 }
00292
00293 std::string Home::href(const std::string& url, const std::string& description)
00294 {
00295 return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
00296 }
00297
00298 WWidget *Home::community()
00299 {
00300 return new WText(tr("home.community"));
00301 }
00302
00303 void Home::readReleases(WTable *releaseTable)
00304 {
00305 std::ifstream f((filePrefix() + "releases.txt").c_str());
00306
00307 releaseTable->clear();
00308
00309 releaseTable->elementAt(0, 0)
00310 ->addWidget(new WText(tr("home.download.version")));
00311 releaseTable->elementAt(0, 1)
00312 ->addWidget(new WText(tr("home.download.date")));
00313 releaseTable->elementAt(0, 2)
00314 ->addWidget(new WText(tr("home.download.description")));
00315
00316 releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
00317 WLength::Auto);
00318 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00319 WLength::Auto);
00320
00321 int row = 1;
00322
00323 while (f) {
00324 std::string line;
00325 getline(f, line);
00326
00327 if (f) {
00328 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00329 CsvTokenizer;
00330 CsvTokenizer tok(line);
00331
00332 CsvTokenizer::iterator i=tok.begin();
00333
00334 std::string fileName = *i;
00335 std::string description = *(++i);
00336 releaseTable->elementAt(row, 0)->addWidget
00337 (new WText(href("http://prdownloads.sourceforge.net/witty/"
00338 + fileName + "?download", description)));
00339 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00340 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00341
00342 ++row;
00343 }
00344 }
00345 }
00346
00347 WString Home::tr(const char *key)
00348 {
00349 return WString::tr(key);
00350 }
00351
00352 void Home::googleAnalyticsLogger()
00353 {
00354 std::string googleCmd =
00355 "if (window.pageTracker) {"
00356 """try {"
00357 "" "window.pageTracker._trackPageview(\""
00358 + environment().deploymentPath() + internalPath() + "\");"
00359 """} catch (e) { }"
00360 "}";
00361
00362 doJavaScript(googleCmd);
00363 }
00364