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

Generated on Tue Mar 22 2016 for the C++ Web Toolkit (Wt) by doxygen 1.7.6.1