Wt examples  3.2.1
/home/koen/project/wt/public-git/wt/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       createHome();
00101       root()->addWidget(homePage_);
00102 
00103       setLanguageFromPath();
00104     }
00105   }
00106 }
00107 
00108 void Home::createHome()
00109 {
00110   WTemplate *result = new WTemplate(tr("template"), root());
00111   homePage_ = result;
00112 
00113   WContainerWidget *languagesDiv = new WContainerWidget();
00114   languagesDiv->setId("top_languages");
00115 
00116   for (unsigned i = 0; i < languages.size(); ++i) {
00117     if (i != 0)
00118       new WText("- ", languagesDiv);
00119 
00120     const Lang& l = languages[i];
00121 
00122     new WAnchor(WLink(WLink::InternalPath, l.path_),
00123                 WString::fromUTF8(l.longDescription_), languagesDiv);
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 
00177 void Home::setLanguage(int index)
00178 {
00179   if (homePage_) {
00180     const Lang& l = languages[index];
00181 
00182     setLocale(l.code_);
00183 
00184     std::string langPath = l.path_;
00185     mainMenu_->setInternalBasePath(langPath);
00186     examplesMenu_->setInternalBasePath(langPath + "examples");
00187     BlogView *blog = dynamic_cast<BlogView *>(findWidget("blog"));
00188     if (blog)
00189       blog->setInternalBasePath(langPath + "blog/");
00190     updateTitle();
00191 
00192     language_ = index;
00193   }
00194 }
00195 
00196 WWidget *Home::linkSourceBrowser(const std::string& example)
00197 {
00198   /*
00199    * Instead of using a WAnchor, which will not progress properly because
00200    * it is wrapped with wrapView() (-- should we not fix that?), we use
00201    * a WText which contains an anchor, and enable internal path encoding.
00202    */
00203   std::string path = "#/" + SRC_INTERNAL_PATH + "/" + example;
00204   WText *a = new WText(tr("source-browser-link").arg(path));
00205   a->setInternalPathEncoding(true);
00206   return a;
00207 }
00208 
00209 void Home::setLanguageFromPath()
00210 {
00211   std::string langPath = internalPathNextPart("/");
00212 
00213   if (langPath.empty())
00214     langPath = '/';
00215   else
00216     langPath = '/' + langPath + '/';
00217 
00218   int newLanguage = 0;
00219 
00220   for (unsigned i = 0; i < languages.size(); ++i) {
00221     if (languages[i].path_ == langPath) {
00222       newLanguage = i;
00223       break;
00224     }
00225   }
00226 
00227   if (newLanguage != language_)
00228     setLanguage(newLanguage);
00229 }
00230 
00231 void Home::updateTitle()
00232 {
00233   if (mainMenu_->currentItem()) {
00234     setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
00235   }
00236 }
00237 
00238 void Home::logInternalPath(const std::string& path)
00239 {
00240   // simulate an access log for the interal paths
00241   log("path") << path;
00242 
00243   // If this goes to /src, we need to invoke google analytics method too
00244   if (path.size() >= 4 && path.substr(0, 4) == "/src") {
00245     googleAnalyticsLogger();
00246   }
00247 }
00248 
00249 WWidget *Home::introduction()
00250 {
00251   return new WText(tr("home.intro"));
00252 }
00253 
00254 WWidget *Home::blog()
00255 {
00256   const Lang& l = languages[language_];
00257   std::string langPath = l.path_;
00258   BlogView *blog = new BlogView(langPath + "blog/",
00259                                 appRoot() + "blog.db", "/wt/blog/feed/");
00260   blog->setObjectName("blog");
00261 
00262   if (!blog->user().empty())
00263     chatSetUser(blog->user());
00264 
00265   blog->userChanged().connect(this, &Home::chatSetUser);
00266 
00267   return blog;
00268 }
00269 
00270 void Home::chatSetUser(const WString& userName)
00271 {
00272   WApplication::instance()->doJavaScript
00273     ("if (window.chat) "
00274      "try {"
00275      """window.chat.emit(window.chat, 'login', "
00276      ""                   "" + userName.jsStringLiteral() + "); "
00277      "} catch (e) {"
00278      """window.chatUser = " + userName.jsStringLiteral() + ";"
00279      "}"
00280      "else "
00281      """window.chatUser = " + userName.jsStringLiteral() + ";");
00282 }
00283 
00284 WWidget *Home::status()
00285 {
00286   return new WText(tr("home.status"));
00287 }
00288 
00289 WWidget *Home::features()
00290 {
00291   return new WText(tr("home.features"));
00292 }
00293 
00294 WWidget *Home::documentation()
00295 {
00296   WText *result = new WText(tr("home.documentation"));
00297   result->setInternalPathEncoding(true);
00298   return result;
00299 }
00300 
00301 WWidget *Home::otherLanguage()
00302 {
00303   return new WText(tr("home.other-language"));
00304 }
00305 
00306 WWidget *Home::wrapView(WWidget *(Home::*createWidget)())
00307 {
00308   return makeStaticModel(boost::bind(createWidget, this));
00309 }
00310 
00311 std::string Home::href(const std::string& url, const std::string& description)
00312 {
00313   return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
00314 }
00315 
00316 WWidget *Home::community()
00317 {
00318   return new WText(tr("home.community"));
00319 }
00320 
00321 void Home::readReleases(WTable *releaseTable)
00322 {
00323   std::ifstream f((filePrefix() + "releases.txt").c_str());
00324 
00325   releaseTable->clear();
00326 
00327   releaseTable->elementAt(0, 0)
00328     ->addWidget(new WText(tr("home.download.version")));
00329   releaseTable->elementAt(0, 1)
00330     ->addWidget(new WText(tr("home.download.date")));
00331   releaseTable->elementAt(0, 2)
00332     ->addWidget(new WText(tr("home.download.description")));
00333 
00334   releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
00335                                         WLength::Auto);
00336   releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00337                                         WLength::Auto);
00338 
00339   int row = 1;
00340 
00341   while (f) {
00342     std::string line;
00343     getline(f, line);
00344 
00345     if (f) {
00346       typedef boost::tokenizer<boost::escaped_list_separator<char> >
00347         CsvTokenizer;
00348       CsvTokenizer tok(line);
00349 
00350       CsvTokenizer::iterator i=tok.begin();
00351 
00352       std::string fileName = *i;
00353       std::string description = *(++i);
00354       releaseTable->elementAt(row, 0)->addWidget
00355         (new WText(href("http://prdownloads.sourceforge.net/witty/" 
00356                         + fileName + "?download", description)));
00357       releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00358       releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00359 
00360       ++row;
00361     }
00362   }
00363 }
00364 
00365 #ifdef WT_EMWEB_BUILD
00366 WWidget *Home::quoteForm()
00367 {
00368   WContainerWidget *result = new WContainerWidget();
00369   result->setStyleClass("quote");
00370 
00371   WTemplate *requestTemplate = new WTemplate(tr("quote.request"), result);
00372 
00373   WPushButton *quoteButton = new WPushButton(tr("quote.requestbutton"));
00374   requestTemplate->bindWidget("button", quoteButton);
00375 
00376   WWidget *quoteForm = createQuoteForm();
00377   result->addWidget(quoteForm);
00378 
00379   quoteButton->clicked().connect(quoteForm, &WWidget::show);
00380   quoteButton->clicked().connect(requestTemplate, &WWidget::hide);
00381 
00382   quoteForm->hide();
00383 
00384   return result;
00385 }
00386 #endif // WT_EMWEB_BUILD
00387 
00388 WWidget *Home::download()
00389 {
00390   WContainerWidget *result = new WContainerWidget();
00391   result->addWidget(new WText(tr("home.download")));
00392 
00393   result->addWidget(new WText(tr("home.download.license")));
00394 
00395 #ifdef WT_EMWEB_BUILD
00396   result->addWidget(quoteForm());
00397 #endif // WT_EMWEB_BUILD
00398 
00399   result->addWidget(new WText(tr("home.download.packages")));
00400 
00401   releases_ = new WTable();
00402   readReleases(releases_);
00403   result->addWidget(releases_);
00404 
00405   result->addWidget(new WText(tr("home.download.other")));
00406 
00407   return result;
00408 }
00409 
00410 
00411 WString Home::tr(const char *key)
00412 {
00413   return WString::tr(key);
00414 }
00415 
00416 void Home::googleAnalyticsLogger()
00417 {
00418   std::string googleCmd = 
00419     "if (window.pageTracker) {"
00420     """try {"
00421     ""  "setTimeout(function() {"
00422     ""  "window.pageTracker._trackPageview(\""
00423     + environment().deploymentPath() + internalPath() + "\");"
00424     ""  "}, 1000);"
00425     """} catch (e) { }"
00426     "}";
00427 
00428   doJavaScript(googleCmd);
00429 }
00430 

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