Wt examples 3.3.12
ExampleSourceViewer.C
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009 Emweb bvba
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7#include <iostream>
8#include <stdlib.h>
9#include <algorithm>
10
11#include <Wt/WApplication>
12#include <Wt/WContainerWidget>
13#include <Wt/WEnvironment>
14#include <Wt/WLineEdit>
15#include <Wt/WGridLayout>
16#include <Wt/WHBoxLayout>
17#include <Wt/WPushButton>
18#include <Wt/WTable>
19#include <Wt/WText>
20#include <Wt/WTreeView>
21#include <Wt/WVBoxLayout>
22#include <Wt/WViewWidget>
23
24#include <boost/filesystem/operations.hpp>
25#include <boost/filesystem/exception.hpp>
26#include <boost/filesystem/convenience.hpp>
27#include <boost/algorithm/string.hpp>
28
29#include "ExampleSourceViewer.h"
30#include "FileItem.h"
31
32using namespace Wt;
33namespace fs = boost::filesystem;
34
35// Same as p.filename() in latest boost::filesystem
36static std::string filename(const fs::path& p)
37{
38#if BOOST_FILESYSTEM_VERSION < 3
39 return p.empty() ? std::string() : *--p.end();
40#else
41 return p.empty() ? std::string() : (*--p.end()).string();
42#endif
43}
44
45// Same as p.stem() in latest boost::filesystem
46static std::string stem(const fs::path& p)
47{
48 std::string fn = filename(p);
49 std::size_t pos = fn.find('.');
50 if (pos == std::string::npos)
51 return fn;
52 else
53 return fn.substr(0, pos);
54}
55
56// Should be same as p.parent_path() in latest boost::filesystem
57// This is not entirely according to fs::path::parent_path() in 1.39.0
58fs::path parent_path(const fs::path& p)
59{
60 std::string fn = filename(p);
61 std::string path = p.string();
62
63 return path.substr(0, path.length() - fn.length() - 1);
64}
65
66static bool comparePaths(const fs::path& p1, const fs::path& p2)
67{
68 return filename(p1) > filename(p2);
69}
70
71ExampleSourceViewer::ExampleSourceViewer(const std::string& deployPath,
72 const std::string& examplesRoot,
73 const std::string& examplesType)
74 : deployPath_(deployPath),
75 examplesRoot_(examplesRoot),
76 examplesType_(examplesType)
77{
78 wApp->internalPathChanged().connect
80
82}
83
85{
86 WApplication *app = wApp;
87
89 std::string example = app->internalPathNextPart(deployPath_);
90
91 if (example.find("..") != std::string::npos
92 || example.find('/') != std::string::npos
93 || example.find('\\') != std::string::npos) {
94 app->setInternalPathValid(false);
95 setExample("INVALID_DIR", "INVALID");
96 } else
97 setExample(examplesRoot_ + example, example);
98 }
99}
100
101void ExampleSourceViewer::setExample(const std::string& exampleDir,
102 const std::string& example)
103{
104 clear();
105
106 bool exists = false;
107 try {
108 exists = fs::exists(exampleDir);
109 } catch (std::exception&) {
110 }
111
112 if (!exists) {
113 WApplication::instance()->setInternalPathValid(false);
114 addWidget(new WText("No such example: " + exampleDir));
115 return;
116 }
117
118 model_ = new WStandardItemModel(0, 1, this);
119 if (examplesType_ == "CPP") {
121 } else if (examplesType_ == "JAVA") {
123 }
124
125 WApplication::instance()->setTitle(tr("srcview.title." + example));
126 WText *title =
127 new WText(tr("srcview.title." + examplesType_ + "." + example));
128 title->setInternalPathEncoding(true);
129
130 exampleView_ = new WTreeView();
140
144 sourceView_->setStyleClass("source-view");
145
146 /*
147 * Expand path to first file, to show something in the source viewer
148 */
149 WStandardItem *w = model_->item(0);
150 do {
151 exampleView_->setExpanded(w->index(), true);
152 if (w->rowCount() > 0)
153 w = w->child(0);
154 else {
156 w = 0;
157 }
158 } while (w);
159
160 WVBoxLayout *topLayout = new WVBoxLayout();
161 topLayout->addWidget(title);
162
163 WHBoxLayout *gitLayout = new WHBoxLayout();
164 gitLayout->addWidget(exampleView_, 0);
165 gitLayout->addWidget(sourceView_, 1);
166 topLayout->addLayout(gitLayout, 1);
167 gitLayout->setResizable(0);
168
169 /*
170 * FIXME, in plain HTML mode, we should set a minimum size to the source
171 * view, and remove this in enableAjax() ?
172 */
173 // sourceView_->setHeight("100%");
174
175 setLayout(topLayout);
176 setStyleClass("maindiv");
177}
178
179/*
180 * Return the companion implementation/header file for a C++ source file.
181 */
182static fs::path getCompanion(const fs::path& path)
183{
184 std::string ext = fs::extension(path);
185
186 if (ext == ".h")
187 return parent_path(path) / (stem(path) + ".C");
188 else if (ext == ".C" || ext == ".cpp")
189 return parent_path(path) / (stem(path) + ".h");
190 else
191 return fs::path();
192}
193
195 const fs::path& path)
196{
197 static const char *supportedFiles[] = {
198 ".C", ".cpp", ".h", ".css", ".xml", ".png", ".gif", ".csv", ".ico", 0
199 };
200
201 FileItem* dir = new FileItem("/icons/yellow-folder-open.png", filename(path),
202 "");
203 parent->appendRow(dir);
204 parent = dir;
205 try {
206 std::set<fs::path> paths;
207
208 fs::directory_iterator end_itr;
209 for (fs::directory_iterator i(path); i != end_itr; ++i)
210 paths.insert(*i);
211
212 std::vector<FileItem*> classes, files;
213 std::vector<fs::path> dirs;
214
215 while (!paths.empty()) {
216 fs::path p = *paths.begin();
217 paths.erase(p);
218
219 // skip symbolic links and other files
220 if (fs::is_symlink(p))
221 continue;
222
223 // skip files with an extension we do not want to handle
224 if (fs::is_regular(p)) {
225 std::string ext = fs::extension(p);
226 bool supported = false;
227 for (const char **s = supportedFiles; *s != 0; ++s)
228 if (*s == ext) {
229 supported = true;
230 break;
231 }
232
233 if (!supported)
234 continue;
235 }
236
237 // see if we have one file of a class (.C, .h)
238 fs::path companion = getCompanion(p);
239 if (!companion.empty()) {
240 std::set<fs::path>::iterator it_companion = paths.find(companion);
241
242 if (it_companion != paths.end()) {
243 std::string className = stem(p);
244 escapeText(className);
245 std::string label = "<i>class</i> " + className;
246
247 FileItem *classItem =
248 new FileItem("/icons/cppclass.png", label, std::string());
249 classItem->setFlags(classItem->flags() | ItemIsXHTMLText);
250
251 FileItem *header = new FileItem("/icons/document.png", filename(p),
252 p.string());
253 FileItem *cpp = new FileItem("/icons/document.png",
254 filename(*it_companion),
255 (*it_companion).string());
256 classItem->appendRow(header);
257 classItem->appendRow(cpp);
258
259 classes.push_back(classItem);
260 paths.erase(it_companion);
261 } else {
262 FileItem *file = new FileItem("/icons/document.png", filename(p),
263 p.string());
264 files.push_back(file);
265 }
266 } else if (fs::is_directory(p)) {
267 dirs.push_back(p);
268 } else {
269 FileItem *file = new FileItem("/icons/document.png", filename(p),
270 p.string());
271 files.push_back(file);
272 }
273 }
274
275 std::sort(dirs.begin(), dirs.end(), comparePaths);
276
277 for (unsigned int i = 0; i < classes.size(); i++)
278 parent->appendRow(classes[i]);
279
280 for (unsigned int i = 0; i < files.size(); i++)
281 parent->appendRow(files[i]);
282
283 for (unsigned int i = 0; i < dirs.size(); i++)
284 cppTraverseDir(parent, dirs[i]);
285 } catch (fs::filesystem_error& e) {
286 std::cerr << e.what() << std::endl;
287 }
288}
289
291 const fs::path& srcPath,
292 const std::string packageName)
293{
294 fs::directory_iterator end_itr;
295
296 FileItem *packageItem = 0;
297 for (fs::directory_iterator i(srcPath); i != end_itr; ++i) {
298 fs::path p = *i;
299 if (fs::is_regular(p)) {
300 if (!packageItem) {
301 packageItem = new FileItem("/icons/package.png", packageName, "");
302 parent->appendRow(packageItem);
303 }
304
305 FileItem *file = new FileItem("/icons/javaclass.png", filename(p),
306 p.string());
307 packageItem->appendRow(file);
308 }
309 }
310
311 for (fs::directory_iterator i(srcPath); i != end_itr; ++i) {
312 fs::path p = *i;
313 if (fs::is_directory(p)) {
314 std::string pn = packageName;
315 if (!pn.empty())
316 pn += ".";
317 pn += filename(p);
318
320 }
321 }
322}
323
325 const fs::path& path)
326{
327 FileItem* dir = new FileItem("/icons/yellow-folder-open.png", filename(path),
328 "");
329 parent->appendRow(dir);
330 parent = dir;
331
332 std::vector<fs::path> files, dirs;
333
334 fs::directory_iterator end_itr;
335 for (fs::directory_iterator i(path); i != end_itr; ++i) {
336 fs::path p = *i;
337 if (fs::is_directory(p)) {
338 if (filename(p) == "src") {
339 FileItem* dir = new FileItem("/icons/package-folder-open.png",
340 filename(p), "");
341 parent->appendRow(dir);
342 javaTraversePackages(dir, p, "");
343 } else
344 dirs.push_back(p);
345 } else {
346 files.push_back(p);
347 }
348 }
349
350 std::sort(dirs.begin(), dirs.end(), comparePaths);
351 std::sort(files.begin(), files.end(), comparePaths);
352
353 for (unsigned int i = 0; i < dirs.size(); i++)
354 javaTraverseDir(parent, dirs[i]);
355
356 for (unsigned int i = 0; i < files.size(); i++) {
357 FileItem *file = new FileItem("/icons/document.png", filename(files[i]),
358 files[i].string());
359 parent->appendRow(file);
360 }
361}
362
366 if (exampleView_->selectedIndexes().empty())
367 return;
368
369 WModelIndex selected = *exampleView_->selectedIndexes().begin();
370
371 // expand a folder when clicked
372 if (exampleView_->model()->rowCount(selected) > 0
373 && !exampleView_->isExpanded(selected))
374 exampleView_->setExpanded(selected, true);
375
376 // (for a file,) load data in source viewer
377 sourceView_->setIndex(selected);
378}
static fs::path getCompanion(const fs::path &path)
static std::string stem(const fs::path &p)
static std::string filename(const fs::path &p)
static bool comparePaths(const fs::path &p1, const fs::path &p2)
fs::path parent_path(const fs::path &p)
void setExample(const std::string &exampleDir, const std::string &example)
Wt::WStandardItemModel * model_
void javaTraversePackages(Wt::WStandardItem *parent, const boost::filesystem::path &srcPath, const std::string packageName)
ExampleSourceViewer(const std::string &deployPath, const std::string &examplesRoot, const std::string &examplesType)
Constructor.
Wt::WTreeView * exampleView_
void showFile()
Displayed the currently selected file.
void javaTraverseDir(Wt::WStandardItem *parent, const boost::filesystem::path &path)
void cppTraverseDir(Wt::WStandardItem *parent, const boost::filesystem::path &path)
WStandardItem which stores a file.
Definition FileItem.h:29
static const int FilePathRole
Definition FileItem.h:32
static const int FileNameRole
Definition FileItem.h:33
static const int ContentsRole
Definition FileItem.h:31
View class for source code.
Definition SourceView.h:27
bool setIndex(const Wt::WModelIndex &index)
Sets the model index.
Definition SourceView.C:30
virtual Wt::Signals::connection connect(WObject *target, WObject::Method method)
virtual int rowCount(const WModelIndex &parent=WModelIndex()) const=0
WModelIndexSet selectedIndexes() const
Signal & selectionChanged()
WAbstractItemModel * model() const
void select(const WModelIndex &index, SelectionFlag option=Select)
void setSortingEnabled(bool enabled)
void setSelectionMode(SelectionMode mode)
std::string internalPathNextPart(const std::string &path) const
bool internalPathMatches(const std::string &path) const
void setInternalPathValid(bool valid)
void addLayout(WLayout *layout, int stretch=0, WFlags< AlignmentFlag > alignment=0)
void addWidget(WWidget *widget, int stretch=0, WFlags< AlignmentFlag > alignment=0)
void setResizable(int index, bool enabled=true, const WLength &initialSize=WLength::Auto)
void setLayout(WLayout *layout)
virtual void addWidget(WWidget *widget)
virtual void clear()
static WLength Auto
WStandardItem * invisibleRootItem() const
WStandardItem * item(int row, int column=0) const
WModelIndex index() const
WFlags< ItemFlag > flags() const
void appendRow(const std::vector< WStandardItem * > &items)
int rowCount() const
WStandardItem * child(int row, int column=0) const
void setFlags(WFlags< ItemFlag > flags)
void setInternalPathEncoding(bool enabled)
bool isExpanded(const WModelIndex &index) const
virtual void setModel(WAbstractItemModel *model)
virtual void resize(const WLength &width, const WLength &height)
virtual void setAlternatingRowColors(bool enable)
void setExpanded(const WModelIndex &, bool expanded)
virtual void setHeaderHeight(const WLength &height)
void expandToDepth(int depth)
static WString escapeText(const WString &text, bool newlinesToo=false)
virtual void setStyleClass(const WString &styleClass)
static WString tr(const char *key)
WWidget * parent() const
ItemIsXHTMLText
SingleSelection

Generated on Fri May 17 2024 for the C++ Web Toolkit (Wt) by doxygen 1.9.8