Wt examples 3.1.10
/build/buildd/witty-3.1.10/examples/wt-homepage/Home.C
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
00003  *
00004  * See the LICENSE file for terms of use.
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    * This function switches between the two major components of the homepage,
00072    * depending on the internal path:
00073    * /src -> source viewer
00074    * /... -> homepage
00075    *
00076    * FIXME: we should take into account language /cn/src ...
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   // Make the menu be internal-path aware.
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    * Instead of using a WAnchor, which will not progress properly because
00199    * it is wrapped with wrapView() (-- should we not fix that?), we use
00200    * a WText which contains an anchor, and enable internal path encoding.
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   // simulate an access log for the interal paths
00240   log("path") << path;
00241 
00242   // If this goes to /src, we need to invoke google analytics method too
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 

Generated on Wed Jul 27 2011 for the C++ Web Toolkit (Wt) by doxygen 1.7.4