Wt examples  3.7.1
Home.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include <fstream>
8 #include <iostream>
9 
10 #include <boost/lexical_cast.hpp>
11 #include <boost/tokenizer.hpp>
12 #include <boost/algorithm/string.hpp>
13 
14 #include <Wt/WAnchor>
15 #include <Wt/WApplication>
16 #include <Wt/WEnvironment>
17 #include <Wt/WLogger>
18 #include <Wt/WMenu>
19 #include <Wt/WPushButton>
20 #include <Wt/WStackedWidget>
21 #include <Wt/WTabWidget>
22 #include <Wt/WTable>
23 #include <Wt/WTableCell>
24 #include <Wt/WTemplate>
25 #include <Wt/WText>
26 #include <Wt/WViewWidget>
27 #include <Wt/WVBoxLayout>
28 
29 #include "Home.h"
30 #include "view/BlogView.h"
31 
32 static const std::string SRC_INTERNAL_PATH = "src";
33 
35 {
36 }
37 
40  const std::string& title, const std::string& resourceBundle,
41  const std::string& cssPath)
42  : WApplication(env),
43  releases_(0),
44  blogDb_(blogDb),
45  homePage_(0),
46  sourceViewer_(0)
47 {
48  messageResourceBundle().use(appRoot() + resourceBundle, false);
49 
50  useStyleSheet(cssPath + "/wt.css");
51  useStyleSheet(cssPath + "/wt_ie.css", "lt IE 7", "all");
52  useStyleSheet("css/home.css");
53  useStyleSheet("css/sourceview.css");
54  useStyleSheet("css/chatwidget.css");
55  useStyleSheet("css/chatwidget_ie6.css", "lt IE 7", "all");
56  setTitle(title);
57 
58  setLocale("");
59  language_ = 0;
60 }
61 
62 void Home::init()
63 {
67 
68  setup();
69 
71 }
72 
74 {
75  /*
76  * This function switches between the two major components of the homepage,
77  * depending on the internal path:
78  * /src -> source viewer
79  * /... -> homepage
80  *
81  * FIXME: we should take into account language /cn/src ...
82  */
83  std::string base = internalPathNextPart("/");
84 
85  if (base == SRC_INTERNAL_PATH) {
86  if (!sourceViewer_) {
87  delete homePage_;
88  homePage_ = 0;
89 
90  root()->clear();
91 
93  WVBoxLayout *layout = new WVBoxLayout();
94  layout->setContentsMargins(0, 0, 0, 0);
95  layout->addWidget(sourceViewer_);
96  root()->setLayout(layout);
97  }
98  } else {
99  if (!homePage_) {
100  delete sourceViewer_;
101  sourceViewer_ = 0;
102 
103  root()->clear();
104 
105  createHome();
107 
109  }
110  }
111 }
112 
114 {
115  WTemplate *result = new WTemplate(tr("template"), root());
116  homePage_ = result;
117 
118  WContainerWidget *languagesDiv = new WContainerWidget();
119  languagesDiv->setId("top_languages");
120 
121  for (unsigned i = 0; i < languages.size(); ++i) {
122  if (i != 0)
123  new WText("- ", languagesDiv);
124 
125  const Lang& l = languages[i];
126 
127  new WAnchor(WLink(WLink::InternalPath, l.path_),
128  WString::fromUTF8(l.longDescription_), languagesDiv);
129  }
130 
131  WStackedWidget *contents = new WStackedWidget();
132  WAnimation fade(WAnimation::Fade, WAnimation::Linear, 250);
133  contents->setTransitionAnimation(fade);
134  contents->setId("main_page");
135 
136  mainMenu_ = new WMenu(contents, Vertical);
137 
139  (tr("introduction"), introduction())->setPathComponent("");
140 
142  (tr("blog"), deferCreate(boost::bind(&Home::blog, this)));
143 
145  (tr("features"), wrapView(&Home::features), WMenuItem::PreLoading);
146 
148  (tr("documentation"), wrapView(&Home::documentation),
149  WMenuItem::PreLoading);
150 
152  (tr("examples"), examples(),
153  WMenuItem::PreLoading)->setPathComponent("examples/");
154 
156  (tr("download"), deferCreate(boost::bind(&Home::download, this)),
157  WMenuItem::PreLoading);
158 
160  (tr("community"), wrapView(&Home::community), WMenuItem::PreLoading);
161 
163  (tr("other-language"), wrapView(&Home::otherLanguage),
164  WMenuItem::PreLoading);
165 
167 
169 
170  // Make the menu be internal-path aware.
172 
174 
175  result->bindWidget("languages", languagesDiv);
176  result->bindWidget("menu", mainMenu_);
177  result->bindWidget("contents", contents);
178  result->bindWidget("sidebar", sideBarContent_);
179 }
180 
181 void Home::setLanguage(int index)
182 {
183  if (homePage_) {
184  const Lang& l = languages[index];
185 
186  setLocale(l.code_);
187 
188  std::string langPath = l.path_;
189  mainMenu_->setInternalBasePath(langPath);
190  examplesMenu_->setInternalBasePath(langPath + "examples");
191  BlogView *blog = dynamic_cast<BlogView *>(findWidget("blog"));
192  if (blog)
193  blog->setInternalBasePath(langPath + "blog/");
194  updateTitle();
195 
196  language_ = index;
197  }
198 }
199 
200 WWidget *Home::linkSourceBrowser(const std::string& example)
201 {
202  /*
203  * Instead of using a WAnchor, which will not progress properly because
204  * it is wrapped with wrapView() (-- should we not fix that?), we use
205  * a WText which contains an anchor, and enable internal path encoding.
206  */
207  std::string path = "#/" + SRC_INTERNAL_PATH + "/" + example;
208  WText *a = new WText(tr("source-browser-link").arg(path));
209  a->setInternalPathEncoding(true);
210  return a;
211 }
212 
214 {
215  std::string langPath = internalPathNextPart("/");
216 
217  if (langPath.empty())
218  langPath = '/';
219  else
220  langPath = '/' + langPath + '/';
221 
222  int newLanguage = 0;
223 
224  for (unsigned i = 0; i < languages.size(); ++i) {
225  if (languages[i].path_ == langPath) {
226  newLanguage = i;
227  break;
228  }
229  }
230 
231  if (newLanguage != language_)
232  setLanguage(newLanguage);
233 }
234 
236 {
237  if (mainMenu_->currentItem()) {
238  setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
239  }
240 }
241 
242 void Home::logInternalPath(const std::string& path)
243 {
244  // simulate an access log for the interal paths
245  log("path") << path;
246 
247  // If this goes to /src, we need to invoke google analytics method too
248  if (path.size() >= 4 && path.substr(0, 4) == "/src") {
250  }
251 }
252 
254 {
255  return new WText(tr("home.intro"));
256 }
257 
259 {
260  const Lang& l = languages[language_];
261  std::string langPath = l.path_;
262  BlogView *blog = new BlogView(langPath + "blog/",
263  blogDb_, "/wt/blog/feed/");
264  blog->setObjectName("blog");
265 
266  if (!blog->user().empty())
267  chatSetUser(blog->user());
268 
269  blog->userChanged().connect(this, &Home::chatSetUser);
270 
271  return blog;
272 }
273 
274 void Home::chatSetUser(const WString& userName)
275 {
276  WApplication::instance()->doJavaScript
277  ("if (window.chat && window.chat.emit) {"
278  """try {"
279  "" "window.chat.emit(window.chat, 'login', "
280  "" "" + userName.jsStringLiteral() + "); "
281  """} catch (e) {"
282  "" "window.chatUser=" + userName.jsStringLiteral() + ";"
283  """}"
284  "} else "
285  """window.chatUser=" + userName.jsStringLiteral() + ";");
286 }
287 
289 {
290  return new WText(tr("home.status"));
291 }
292 
294 {
295  return new WText(tr("home.features"));
296 }
297 
299 {
300  WText *result = new WText(tr("home.documentation"));
301  result->setInternalPathEncoding(true);
302  return result;
303 }
304 
306 {
307  return new WText(tr("home.other-language"));
308 }
309 
311 {
312  return makeStaticModel(boost::bind(createWidget, this));
313 }
314 
315 std::string Home::href(const std::string& url, const std::string& description)
316 {
317  return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
318 }
319 
321 {
322  return new WText(tr("home.community"));
323 }
324 
325 void Home::readReleases(WTable *releaseTable)
326 {
327  std::ifstream f((filePrefix() + "releases.txt").c_str());
328 
329  releaseTable->clear();
330 
331  releaseTable->elementAt(0, 0)
332  ->addWidget(new WText(tr("home.download.version")));
333  releaseTable->elementAt(0, 1)
334  ->addWidget(new WText(tr("home.download.date")));
335  releaseTable->elementAt(0, 2)
336  ->addWidget(new WText(tr("home.download.description")));
337 
338  releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
339  WLength::Auto);
340  releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
341  WLength::Auto);
342 
343  int row = 1;
344 
345  while (f) {
346  std::string line;
347  getline(f, line);
348 
349  if (f) {
350  typedef boost::tokenizer<boost::escaped_list_separator<char> >
351  CsvTokenizer;
352  CsvTokenizer tok(line);
353 
354  CsvTokenizer::iterator i=tok.begin();
355 
356  std::string fileName = *i;
357  std::string description = *(++i);
358  releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
359  releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
360 
361  ++i;
362  std::string url = "http://prdownloads.sourceforge.net/witty/"
363  + fileName + "?download";
364  if (i != tok.end())
365  url = *i;
366 
367  releaseTable->elementAt(row, 0)->addWidget
368  (new WText(href(url, description)));
369 
370  ++row;
371  }
372  }
373 }
374 
375 #ifdef WT_EMWEB_BUILD
377 {
378  WContainerWidget *result = new WContainerWidget();
379  result->setStyleClass("quote");
380 
381  WTemplate *requestTemplate = new WTemplate(tr("quote.request"), result);
382 
383  WPushButton *quoteButton = new WPushButton(tr("quote.requestbutton"));
384  requestTemplate->bindWidget("button", quoteButton);
385 
387  result->addWidget(quoteForm);
388 
389  quoteButton->clicked().connect(quoteForm, &WWidget::show);
390  quoteButton->clicked().connect(requestTemplate, &WWidget::hide);
391 
392  quoteForm->hide();
393 
394  return result;
395 }
396 #endif // WT_EMWEB_BUILD
397 
399 {
400  WContainerWidget *result = new WContainerWidget();
401  result->addWidget(new WText(tr("home.download")));
402 
403  result->addWidget(new WText(tr("home.download.license")));
404 
405 #ifdef WT_EMWEB_BUILD
406  result->addWidget(quoteForm());
407 #endif // WT_EMWEB_BUILD
408 
409  result->addWidget(new WText(tr("home.download.packages")));
410 
411  releases_ = new WTable();
413  result->addWidget(releases_);
414 
415  result->addWidget(new WText(tr("home.download.other")));
416 
417  return result;
418 }
419 
420 
421 WString Home::tr(const char *key)
422 {
423  return WString::tr(key);
424 }
425 
427 {
428  doJavaScript("if (window.ga) ga('send','pageview',"
429  + WWebWidget::jsStringLiteral(environment().deploymentPath()
430  + internalPath()) + ");");
431 }
432 
void setLayout(std::unique_ptr< WLayout > layout)
void logInternalPath(const std::string &path)
Definition: Home.C:242
WWidget * quoteForm()
WMenuItem * addItem(const WString &label, std::unique_ptr< WWidget > contents=nullptr, ContentLoading policy=ContentLoading::Lazy)
std::string path_
Definition: Home.h:33
virtual void setStyleClass(const WString &styleClass) override
WWidget * wrapView(WWidget *(Home::*createFunction)())
Definition: Home.C:310
int language_
Definition: Home.h:118
WWidget * linkSourceBrowser(const std::string &examplePath)
Definition: Home.C:200
WWidget * introduction()
Definition: Home.C:253
WMenu * mainMenu_
Definition: Home.h:116
std::string internalPath() const
std::vector< Lang > languages
Definition: Home.h:133
EventSignal< WMouseEvent > & clicked()
std::string url(const std::string &internalPath=std::string()) const
void setLanguage(int language)
Definition: Home.C:181
WMessageResourceBundle & messageResourceBundle()
void addWidget(std::unique_ptr< WWidget > widget, int stretch, WFlags< AlignmentFlag > alignment)
void setTransitionAnimation(const WAnimation &animation, bool autoReverse=false)
virtual void bindWidget(const std::string &varName, std::unique_ptr< WWidget > widget)
void setTitle(const WString &title)
virtual void setId(const std::string &id) override
virtual WWidget * examples()=0
std::string longDescription_
Definition: Home.h:33
const WEnvironment & environment() const
Definition: Home.h:23
WString text() const
WString tr(const char *key)
Definition: Home.C:421
void updateTitle()
Definition: Home.C:235
void setup()
Definition: Home.C:73
WWidget * features()
Definition: Home.C:293
virtual WWidget * sourceViewer(const std::string &deployPath)=0
const WString & title() const
void setInternalPathEnabled(const std::string &basePath="")
Definition: Home.h:67
virtual std::string filePrefix() const =0
std::string jsStringLiteral(char delimiter='\'') const
Home(const WEnvironment &env, Wt::Dbo::SqlConnectionPool &blogDb, const std::string &title, const std::string &resourceBundle, const std::string &cssPath)
Definition: Home.C:38
WTableCell * elementAt(int row, int column)
WWidget * status()
Definition: Home.C:288
static const std::string SRC_INTERNAL_PATH
Definition: Home.C:32
virtual void clear()
Signal< WMenuItem *> & itemSelected()
void setContentsMargins(int left, int top, int right, int bottom)
DeferredWidget< Function > * deferCreate(Function f)
Definition: Home.h:62
WWidget * documentation()
Definition: Home.C:298
Signal< WMenuItem *> & itemSelectRendered()
void use(const std::string &path, bool loadInMemory=true)
WContainerWidget * root() const
Wt::Dbo::SqlConnectionPool & blogDb_
Definition: Home.h:98
std::string href(const std::string &url, const std::string &description)
Definition: Home.C:315
void init()
Definition: Home.C:62
WWidget * homePage_
Definition: Home.h:99
void setInternalBasePath(const std::string &path)
WWidget * findWidget(const std::string &name)
void setInternalPathEncoding(bool enabled)
WTabWidget * examplesMenu_
Definition: Home.h:89
WWidget * otherLanguage()
Definition: Home.C:305
void setLanguageFromPath()
Definition: Home.C:213
WMenuItem * currentItem() const
virtual ~Home()
Definition: Home.C:34
WContainerWidget * sideBarContent_
Definition: Home.h:131
WWidget * blog()
Definition: Home.C:258
WWidget * download()
Definition: Home.C:398
WApplication * createWidget(const WEnvironment &env, SimpleChatServer &server)
Definition: simpleChat.C:145
WLogEntry log(const std::string &type) const
static std::string appRoot()
void setInternalBasePath(const std::string &basePath)
virtual void resize(const WLength &width, const WLength &height) override
void useStyleSheet(const WLink &link, const std::string &media="all")
void chatSetUser(const WString &name)
Definition: Home.C:274
std::string internalPathNextPart(const std::string &path) const
void readReleases(WTable *releaseTable)
Definition: Home.C:325
WWidget * community()
Definition: Home.C:320
virtual void setPathComponent(const std::string &path)
void createHome()
Definition: Home.C:113
void doJavaScript(const std::string &javascript, bool afterLoaded=true)
virtual Wt::Signals::connection connect(WObject *target, WObject::Method method) override
WWidget * sourceViewer_
Definition: Home.h:100
WTable * releases_
Definition: Home.h:94
std::string code_
Definition: Home.h:33
void setLocale(const WLocale &locale)
virtual void addWidget(std::unique_ptr< WWidget > widget)
virtual WWidget * createQuoteForm()=0
Signal< std::string > & internalPathChanged()
virtual void clear()
void googleAnalyticsLogger()
Definition: Home.C:426

Generated on Tue Dec 15 2020 for the C++ Web Toolkit (Wt) by doxygen 1.8.13