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/WPushButton>
00020 #include <Wt/WStackedWidget>
00021 #include <Wt/WTabWidget>
00022 #include <Wt/WTable>
00023 #include <Wt/WTableCell>
00024 #include <Wt/WTemplate>
00025 #include <Wt/WText>
00026 #include <Wt/WViewWidget>
00027 #include <Wt/WVBoxLayout>
00028
00029 #include "Home.h"
00030 #include "view/BlogView.h"
00031
00032 static const std::string SRC_INTERNAL_PATH = "src";
00033
00034 Home::~Home()
00035 {
00036 }
00037
00038 Home::Home(const WEnvironment& env, const std::string& title,
00039 const std::string& resourceBundle, const std::string& cssPath)
00040 : WApplication(env),
00041 releases_(0),
00042 homePage_(0),
00043 sourceViewer_(0)
00044 {
00045 messageResourceBundle().use(appRoot() + resourceBundle, false);
00046
00047 useStyleSheet(cssPath + "/wt.css");
00048 useStyleSheet(cssPath + "/wt_ie.css", "lt IE 7");
00049 useStyleSheet("css/home.css");
00050 useStyleSheet("css/sourceview.css");
00051 setTitle(title);
00052
00053 setLocale("");
00054 language_ = 0;
00055 }
00056
00057 void Home::init()
00058 {
00059 internalPathChanged().connect(this, &Home::setup);
00060 internalPathChanged().connect(this, &Home::setLanguageFromPath);
00061 internalPathChanged().connect(this, &Home::logInternalPath);
00062
00063 setup();
00064
00065 setLanguageFromPath();
00066 }
00067
00068 void Home::setup()
00069 {
00070
00071
00072
00073
00074
00075
00076
00077
00078 std::string base = internalPathNextPart("/");
00079
00080 if (base == SRC_INTERNAL_PATH) {
00081 if (!sourceViewer_) {
00082 delete homePage_;
00083 homePage_ = 0;
00084
00085 root()->clear();
00086
00087 sourceViewer_ = sourceViewer("/" + SRC_INTERNAL_PATH + "/");
00088 WVBoxLayout *layout = new WVBoxLayout();
00089 layout->setContentsMargins(0, 0, 0, 0);
00090 layout->addWidget(sourceViewer_);
00091 root()->setLayout(layout);
00092 }
00093 } else {
00094 if (!homePage_) {
00095 delete sourceViewer_;
00096 sourceViewer_ = 0;
00097
00098 root()->clear();
00099
00100 homePage_ = initHome();
00101 root()->addWidget(homePage_);
00102
00103 setLanguageFromPath();
00104 }
00105 }
00106 }
00107
00108 WWidget *Home::initHome()
00109 {
00110 WTemplate *result = new WTemplate(tr("template"), root());
00111
00112 WContainerWidget *languagesDiv = new WContainerWidget();
00113 languagesDiv->setId("top_languages");
00114
00115 for (unsigned i = 0; i < languages.size(); ++i) {
00116 if (i != 0)
00117 new WText("- ", languagesDiv);
00118
00119 const Lang& l = languages[i];
00120
00121 WAnchor *a = new WAnchor("", WString::fromUTF8(l.longDescription_),
00122 languagesDiv);
00123 a->setRefInternalPath(l.path_);
00124 }
00125
00126 WStackedWidget *contents = new WStackedWidget();
00127 WAnimation fade(WAnimation::Fade, WAnimation::Linear, 250);
00128 contents->setTransitionAnimation(fade);
00129 contents->setId("main_page");
00130
00131 mainMenu_ = new WMenu(contents, Vertical);
00132 mainMenu_->setRenderAsList(true);
00133
00134 mainMenu_->addItem
00135 (tr("introduction"), introduction())->setPathComponent("");
00136
00137 mainMenu_->addItem
00138 (tr("blog"), deferCreate(boost::bind(&Home::blog, this)));
00139
00140 mainMenu_->addItem
00141 (tr("features"), wrapView(&Home::features), WMenuItem::PreLoading);
00142
00143 mainMenu_->addItem
00144 (tr("documentation"), wrapView(&Home::documentation),
00145 WMenuItem::PreLoading);
00146
00147 mainMenu_->addItem
00148 (tr("examples"), examples(),
00149 WMenuItem::PreLoading)->setPathComponent("examples/");
00150
00151 mainMenu_->addItem
00152 (tr("download"), deferCreate(boost::bind(&Home::download, this)),
00153 WMenuItem::PreLoading);
00154
00155 mainMenu_->addItem
00156 (tr("community"), wrapView(&Home::community), WMenuItem::PreLoading);
00157
00158 mainMenu_->addItem
00159 (tr("other-language"), wrapView(&Home::otherLanguage),
00160 WMenuItem::PreLoading);
00161
00162 mainMenu_->itemSelectRendered().connect(this, &Home::updateTitle);
00163
00164 mainMenu_->itemSelected().connect(this, &Home::googleAnalyticsLogger);
00165
00166
00167 mainMenu_->setInternalPathEnabled("/");
00168
00169 sideBarContent_ = new WContainerWidget();
00170
00171 result->bindWidget("languages", languagesDiv);
00172 result->bindWidget("menu", mainMenu_);
00173 result->bindWidget("contents", contents);
00174 result->bindWidget("sidebar", sideBarContent_);
00175
00176 return result;
00177 }
00178
00179 void Home::setLanguage(int index)
00180 {
00181 if (homePage_) {
00182 const Lang& l = languages[index];
00183
00184 setLocale(l.code_);
00185
00186 std::string langPath = l.path_;
00187 mainMenu_->setInternalBasePath(langPath);
00188 examplesMenu_->setInternalBasePath(langPath + "examples");
00189 updateTitle();
00190
00191 language_ = index;
00192 }
00193 }
00194
00195 WWidget *Home::linkSourceBrowser(const std::string& example)
00196 {
00197
00198
00199
00200
00201
00202 std::string path = "#/" + SRC_INTERNAL_PATH + "/" + example;
00203 WText *a = new WText(tr("source-browser-link").arg(path));
00204 a->setInternalPathEncoding(true);
00205 return a;
00206 }
00207
00208 void Home::setLanguageFromPath()
00209 {
00210 std::string langPath = internalPathNextPart("/");
00211
00212 if (langPath.empty())
00213 langPath = '/';
00214 else
00215 langPath = '/' + langPath + '/';
00216
00217 int newLanguage = 0;
00218
00219 for (unsigned i = 0; i < languages.size(); ++i) {
00220 if (languages[i].path_ == langPath) {
00221 newLanguage = i;
00222 break;
00223 }
00224 }
00225
00226 if (newLanguage != language_)
00227 setLanguage(newLanguage);
00228 }
00229
00230 void Home::updateTitle()
00231 {
00232 if (mainMenu_->currentItem()) {
00233 setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
00234 }
00235 }
00236
00237 void Home::logInternalPath(const std::string& path)
00238 {
00239
00240 log("path") << path;
00241
00242
00243 if (path.size() >= 4 && path.substr(0, 4) == "/src") {
00244 googleAnalyticsLogger();
00245 }
00246 }
00247
00248 WWidget *Home::introduction()
00249 {
00250 return new WText(tr("home.intro"));
00251 }
00252
00253 WWidget *Home::blog()
00254 {
00255 BlogView *blog = new BlogView("/blog/", appRoot() + "blog.db", "/wt/blog/feed/");
00256
00257 if (!blog->user().empty())
00258 chatSetUser(blog->user());
00259
00260 blog->userChanged().connect(this, &Home::chatSetUser);
00261
00262 return blog;
00263 }
00264
00265 void Home::chatSetUser(const WString& userName)
00266 {
00267 WApplication::instance()->doJavaScript
00268 ("if (window.chat) "
00269 "try {"
00270 """window.chat.emit(window.chat, 'login', "
00271 "" "" + userName.jsStringLiteral() + "); "
00272 "} catch (e) {"
00273 """window.chatUser = " + userName.jsStringLiteral() + ";"
00274 "}"
00275 "else "
00276 """window.chatUser = " + userName.jsStringLiteral() + ";");
00277 }
00278
00279 WWidget *Home::status()
00280 {
00281 return new WText(tr("home.status"));
00282 }
00283
00284 WWidget *Home::features()
00285 {
00286 return new WText(tr("home.features"));
00287 }
00288
00289 WWidget *Home::documentation()
00290 {
00291 WText *result = new WText(tr("home.documentation"));
00292 result->setInternalPathEncoding(true);
00293 return result;
00294 }
00295
00296 WWidget *Home::otherLanguage()
00297 {
00298 return new WText(tr("home.other-language"));
00299 }
00300
00301 WWidget *Home::wrapView(WWidget *(Home::*createWidget)())
00302 {
00303 return makeStaticModel(boost::bind(createWidget, this));
00304 }
00305
00306 std::string Home::href(const std::string& url, const std::string& description)
00307 {
00308 return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
00309 }
00310
00311 WWidget *Home::community()
00312 {
00313 return new WText(tr("home.community"));
00314 }
00315
00316 void Home::readReleases(WTable *releaseTable)
00317 {
00318 std::ifstream f((filePrefix() + "releases.txt").c_str());
00319
00320 releaseTable->clear();
00321
00322 releaseTable->elementAt(0, 0)
00323 ->addWidget(new WText(tr("home.download.version")));
00324 releaseTable->elementAt(0, 1)
00325 ->addWidget(new WText(tr("home.download.date")));
00326 releaseTable->elementAt(0, 2)
00327 ->addWidget(new WText(tr("home.download.description")));
00328
00329 releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
00330 WLength::Auto);
00331 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00332 WLength::Auto);
00333
00334 int row = 1;
00335
00336 while (f) {
00337 std::string line;
00338 getline(f, line);
00339
00340 if (f) {
00341 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00342 CsvTokenizer;
00343 CsvTokenizer tok(line);
00344
00345 CsvTokenizer::iterator i=tok.begin();
00346
00347 std::string fileName = *i;
00348 std::string description = *(++i);
00349 releaseTable->elementAt(row, 0)->addWidget
00350 (new WText(href("http://prdownloads.sourceforge.net/witty/"
00351 + fileName + "?download", description)));
00352 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00353 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00354
00355 ++row;
00356 }
00357 }
00358 }
00359
00360 #ifdef WT_EMWEB_BUILD
00361 WWidget *Home::quoteForm()
00362 {
00363 WContainerWidget *result = new WContainerWidget();
00364 result->setStyleClass("quote");
00365
00366 WTemplate *requestTemplate = new WTemplate(tr("quote.request"), result);
00367
00368 WPushButton *quoteButton = new WPushButton(tr("quote.requestbutton"));
00369 requestTemplate->bindWidget("button", quoteButton);
00370
00371 WWidget *quoteForm = createQuoteForm();
00372 result->addWidget(quoteForm);
00373
00374 quoteButton->clicked().connect(quoteForm, &WWidget::show);
00375 quoteButton->clicked().connect(requestTemplate, &WWidget::hide);
00376
00377 quoteForm->hide();
00378
00379 return result;
00380 }
00381 #endif // WT_EMWEB_BUILD
00382
00383 WWidget *Home::download()
00384 {
00385 WContainerWidget *result = new WContainerWidget();
00386 result->addWidget(new WText(tr("home.download")));
00387
00388 result->addWidget(new WText(tr("home.download.license")));
00389
00390 #ifdef WT_EMWEB_BUILD
00391 result->addWidget(quoteForm());
00392 #endif // WT_EMWEB_BUILD
00393
00394 result->addWidget(new WText(tr("home.download.packages")));
00395
00396 releases_ = new WTable();
00397 readReleases(releases_);
00398 result->addWidget(releases_);
00399
00400 result->addWidget(new WText(tr("home.download.other")));
00401
00402 return result;
00403 }
00404
00405
00406 WString Home::tr(const char *key)
00407 {
00408 return WString::tr(key);
00409 }
00410
00411 void Home::googleAnalyticsLogger()
00412 {
00413 std::string googleCmd =
00414 "if (window.pageTracker) {"
00415 """try {"
00416 "" "setTimeout(function() {"
00417 "" "window.pageTracker._trackPageview(\""
00418 + environment().deploymentPath() + internalPath() + "\");"
00419 "" "}, 1000);"
00420 """} catch (e) { }"
00421 "}";
00422
00423 doJavaScript(googleCmd);
00424 }
00425