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