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