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/WIconPair>
00018 #include <Wt/WImage>
00019 #include <Wt/WLineEdit>
00020 #include <Wt/WLogger>
00021 #include <Wt/WMenu>
00022 #include <Wt/WPushButton>
00023 #include <Wt/WStackedWidget>
00024 #include <Wt/WVBoxLayout>
00025 #include <Wt/WTabWidget>
00026 #include <Wt/WTable>
00027 #include <Wt/WTableCell>
00028 #include <Wt/WText>
00029 #include <Wt/WViewWidget>
00030
00031 #include "Home.h"
00032
00033 static const std::string SRC_INTERNAL_PATH = "src";
00034
00035
00036 class Div : public WContainerWidget
00037 {
00038 public:
00039 Div(WContainerWidget *parent, const std::string& id)
00040 : WContainerWidget(parent)
00041 {
00042 setId(id);
00043 }
00044 };
00045
00046 Home::~Home()
00047 {
00048 }
00049
00050 Home::Home(const WEnvironment& env, const std::string& title,
00051 const std::string& resourceBundle, const std::string& cssPath)
00052 : WApplication(env),
00053 recentNews_(0),
00054 historicalNews_(0),
00055 releases_(0),
00056 homePage_(0),
00057 sourceViewer_(0)
00058 {
00059 messageResourceBundle().use(resourceBundle, false);
00060 useStyleSheet(cssPath + "/wt.css");
00061 useStyleSheet(cssPath + "/wt_ie.css", "lt IE 7");
00062 useStyleSheet("home.css");
00063 useStyleSheet("sourceview.css");
00064 setTitle(title);
00065
00066 setLocale("");
00067 language_ = 0;
00068 }
00069
00070 void Home::init()
00071 {
00072 internalPathChanged().connect(SLOT(this, Home::setup));
00073 internalPathChanged().connect(SLOT(this, Home::setLanguageFromPath));
00074 internalPathChanged().connect(SLOT(this, Home::logInternalPath));
00075
00076 setup();
00077 }
00078
00079 void Home::setup()
00080 {
00081
00082
00083
00084
00085
00086
00087 std::string base = internalPathNextPart("/");
00088
00089 if (base == SRC_INTERNAL_PATH) {
00090 if (!sourceViewer_) {
00091 delete homePage_;
00092 homePage_ = 0;
00093
00094 root()->clear();
00095
00096 sourceViewer_ = sourceViewer("/" + SRC_INTERNAL_PATH + "/");
00097 WVBoxLayout *layout = new WVBoxLayout();
00098 layout->setContentsMargins(0, 0, 0, 0);
00099 layout->addWidget(sourceViewer_);
00100 root()->setLayout(layout);
00101 }
00102 } else {
00103 if (!homePage_) {
00104 delete sourceViewer_;
00105 sourceViewer_ = 0;
00106
00107 root()->clear();
00108
00109 homePage_ = initHome();
00110 root()->addWidget(homePage_);
00111 }
00112 }
00113 }
00114
00115 WWidget *Home::initHome()
00116 {
00117 WContainerWidget *result = new WContainerWidget(root());
00118 Div *topWrapper = new Div(result, "top_wrapper");
00119 Div *topContent = new Div(topWrapper, "top_content");
00120
00121 Div *languagesDiv = new Div(topContent, "top_languages");
00122
00123 for (unsigned i = 0; i < languages.size(); ++i) {
00124 if (i != 0)
00125 new WText("- ", languagesDiv);
00126
00127 const Lang& l = languages[i];
00128
00129 WAnchor *a = new WAnchor("", l.longDescription_, languagesDiv);
00130 a->setRefInternalPath(l.path_);
00131 }
00132
00133 WText *topWt = new WText(tr("top_wt"), topContent);
00134 topWt->setInline(false);
00135 topWt->setId("top_wt");
00136
00137 WText *bannerWt = new WText(tr("banner_wrapper"), result);
00138 bannerWt->setId("banner_wrapper");
00139
00140 Div *mainWrapper = new Div(result, "main_wrapper");
00141 Div *mainContent = new Div(mainWrapper, "main_content");
00142 Div *mainMenu = new Div(mainContent, "main_menu");
00143
00144 WStackedWidget *contents = new WStackedWidget();
00145 contents->setId("main_page");
00146
00147 mainMenu_ = new WMenu(contents, Vertical, mainMenu);
00148 mainMenu_->setRenderAsList(true);
00149
00150 mainMenu_->addItem
00151 (tr("introduction"), introduction())->setPathComponent("");
00152
00153 mainMenu_->addItem
00154 (tr("news"), deferCreate(boost::bind(&Home::news, this)),
00155 WMenuItem::PreLoading);
00156
00157 mainMenu_->addItem
00158 (tr("features"), wrapView(&Home::features), WMenuItem::PreLoading);
00159
00160 mainMenu_->addItem
00161 (tr("documentation"), wrapView(&Home::documentation),
00162 WMenuItem::PreLoading);
00163
00164 mainMenu_->addItem
00165 (tr("examples"), examples(),
00166 WMenuItem::PreLoading)->setPathComponent("examples/");
00167
00168 mainMenu_->addItem
00169 (tr("download"), deferCreate(boost::bind(&Home::download, this)),
00170 WMenuItem::PreLoading);
00171
00172 mainMenu_->addItem
00173 (tr("community"), wrapView(&Home::community), WMenuItem::PreLoading);
00174
00175 mainMenu_->addItem
00176 (tr("other-language"), wrapView(&Home::otherLanguage),
00177 WMenuItem::PreLoading);
00178
00179 mainMenu_->itemSelectRendered().connect(SLOT(this, Home::updateTitle));
00180 mainMenu_->itemSelected().connect(SLOT(this, Home::googleAnalyticsLogger));
00181 mainMenu_->select((int)0);
00182
00183
00184 mainMenu_->setInternalPathEnabled("/");
00185
00186 sideBarContent_ = new WContainerWidget(mainMenu);
00187
00188 mainContent->addWidget(contents);
00189 WContainerWidget *clearAll = new WContainerWidget(mainContent);
00190 clearAll->setStyleClass("clearall");
00191
00192 WText *footerWrapper = new WText(tr("footer_wrapper"), result);
00193 footerWrapper->setId("footer_wrapper");
00194
00195 return result;
00196 }
00197
00198 void Home::setLanguage(int index)
00199 {
00200 if (homePage_) {
00201 const Lang& l = languages[index];
00202
00203 setLocale(l.code_);
00204
00205 std::string langPath = l.path_;
00206 mainMenu_->setInternalBasePath(langPath);
00207 examplesMenu_->setInternalBasePath(langPath + "examples");
00208 updateTitle();
00209
00210 language_ = index;
00211 }
00212 }
00213
00214 WWidget *Home::linkSourceBrowser(const std::string& example)
00215 {
00216 WAnchor *a = new WAnchor("", tr("source-browser"));
00217 a->setRefInternalPath("/" + SRC_INTERNAL_PATH + "/" + example);
00218 return a;
00219 }
00220
00221 void Home::setLanguageFromPath()
00222 {
00223 std::string langPath = internalPathNextPart("/");
00224
00225 if (langPath.empty())
00226 langPath = '/';
00227 else
00228 langPath = '/' + langPath + '/';
00229
00230 int newLanguage = 0;
00231
00232 for (unsigned i = 0; i < languages.size(); ++i) {
00233 if (languages[i].path_ == langPath) {
00234 newLanguage = i;
00235 break;
00236 }
00237 }
00238
00239 if (newLanguage != language_)
00240 setLanguage(newLanguage);
00241 }
00242
00243 void Home::updateTitle()
00244 {
00245 if (mainMenu_->currentItem()) {
00246 setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
00247 }
00248 }
00249
00250 void Home::logInternalPath(const std::string& path)
00251 {
00252
00253 log("path") << path;
00254
00255 if (path.size() >= 4 && path.substr(0, 4) == "/src") {
00256 googleAnalyticsLogger();
00257 }
00258 }
00259
00260 WWidget *Home::introduction()
00261 {
00262 return new WText(tr("home.intro"));
00263 }
00264
00265 WWidget *Home::news()
00266 {
00267 WContainerWidget *result = new WContainerWidget();
00268
00269 result->addWidget(new WText(tr("home.news")));
00270
00271 result->addWidget(new WText(tr("home.latest-news")));
00272 recentNews_ = new WTable();
00273 readNews(recentNews_, filePrefix() + "latest-news.txt");
00274 result->addWidget(recentNews_);
00275
00276 result->addWidget(new WText(tr("home.historical-news")));
00277 historicalNews_ = new WTable();
00278 readNews(historicalNews_, filePrefix() + "historical-news.txt");
00279 result->addWidget(historicalNews_);
00280
00281 return result;
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 return new WText(tr("home.documentation"));
00297 }
00298
00299 WWidget *Home::otherLanguage()
00300 {
00301 return new WText(tr("home.other-language"));
00302 }
00303
00304 WWidget *Home::wrapView(WWidget *(Home::*createWidget)())
00305 {
00306 return makeStaticModel(boost::bind(createWidget, this));
00307 }
00308
00309 std::string Home::href(const std::string& url, const std::string& description)
00310 {
00311 return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
00312 }
00313
00314 WWidget *Home::community()
00315 {
00316 return new WText(tr("home.community"));
00317 }
00318
00319 void Home::readNews(WTable *newsTable, const std::string& newsfile)
00320 {
00321 std::ifstream f(newsfile.c_str());
00322
00323 newsTable->clear();
00324
00325 int row = 0;
00326
00327 while (f) {
00328 std::string line;
00329 getline(f, line);
00330
00331 if (f) {
00332 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00333 CsvTokenizer;
00334 CsvTokenizer tok(line);
00335
00336 CsvTokenizer::iterator i=tok.begin();
00337
00338 newsTable->elementAt(row, 0)->
00339 addWidget(new WText("<p><b>" + *i + "</b></p>"));
00340 newsTable->elementAt(row, 0)
00341 ->setContentAlignment(AlignCenter | AlignTop);
00342 newsTable->elementAt(row, 0)
00343 ->resize(WLength(16, WLength::FontEx), WLength::Auto);
00344 newsTable
00345 ->elementAt(row, 1)->addWidget(new WText("<p>" + *(++i) + "</p>"));
00346
00347 ++row;
00348 }
00349 }
00350 }
00351
00352 void Home::readReleases(WTable *releaseTable)
00353 {
00354 std::ifstream f((filePrefix() + "releases.txt").c_str());
00355
00356 releaseTable->clear();
00357
00358 releaseTable->elementAt(0, 0)
00359 ->addWidget(new WText(tr("home.download.version")));
00360 releaseTable->elementAt(0, 1)
00361 ->addWidget(new WText(tr("home.download.date")));
00362 releaseTable->elementAt(0, 2)
00363 ->addWidget(new WText(tr("home.download.description")));
00364
00365 releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
00366 WLength::Auto);
00367 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00368 WLength::Auto);
00369
00370 int row = 1;
00371
00372 while (f) {
00373 std::string line;
00374 getline(f, line);
00375
00376 if (f) {
00377 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00378 CsvTokenizer;
00379 CsvTokenizer tok(line);
00380
00381 CsvTokenizer::iterator i=tok.begin();
00382
00383 std::string fileName = *i;
00384 std::string description = *(++i);
00385 releaseTable->elementAt(row, 0)->addWidget
00386 (new WText(href("http://prdownloads.sourceforge.net/witty/"
00387 + fileName + "?download", description)));
00388 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00389 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00390
00391 ++row;
00392 }
00393 }
00394 }
00395
00396 WString Home::tr(const char *key)
00397 {
00398 return WString::tr(key);
00399 }
00400
00401 void Home::googleAnalyticsLogger()
00402 {
00403 std::string googleCmd =
00404 "if (pageTracker)"
00405 " pageTracker._trackPageview(\"" + environment().deploymentPath() +
00406 internalPath() + "\");";
00407
00408 doJavaScript(googleCmd);
00409 }
00410