Project

General

Profile

Bug #7396 » TreeViewExample.C

Geert Verbruggen, 01/10/2020 02:33 PM

 
/*
* Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
*
* See the LICENSE file for terms of use.
*/
#include "TreeViewExample.h"

#include <iostream>

#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WEnvironment.h>
#include <Wt/WPanel.h>
#include <Wt/WPushButton.h>
#include <Wt/WStandardItem.h>
#include <Wt/WStandardItemModel.h>
#include <Wt/WText.h>
#include <Wt/WTreeView.h>

static const char *weatherIcons[] = {
"sun01.png",
"cloudy01.png",
"w_cloud.png",
"rain.png",
"storm.png",
"snow.png"
};

TreeViewExample::TreeViewExample(std::shared_ptr<WStandardItemModel> model,
const WString& titleText)
: model_(model)
{
belgium_ = model_->item(0, 0)->child(0, 0);

this->addWidget(cpp14::make_unique<WText>(titleText));

/*
* Now create the view
*/
WPanel *panel = this->addWidget(cpp14::make_unique<WPanel>());
panel->resize(600, 300);

// panel->hide();

auto treeView = cpp14::make_unique<WTreeView>();
treeView_ = treeView.get();
panel->setCentralWidget(std::move(treeView));
if (!WApplication::instance()->environment().ajax())
treeView_->resize(WLength::Auto, 290);

treeView_->setAlternatingRowColors(true);
treeView_->setRowHeight(25);
treeView_->setModel(model_);

treeView_->setColumnWidth(1, WLength(100));
treeView_->setColumnAlignment(1, AlignmentFlag::Center);
treeView_->setColumnWidth(3, WLength(100));
treeView_->setColumnAlignment(3, AlignmentFlag::Center);

treeView_->setRowHeaderCount(1);
treeView_->setColumnWidth(0, 300);

/*
* Expand the first (and single) top level node
*/
treeView_->setExpanded(model->index(0, 0), true);
treeView_->setExpanded(model->index(0, 0, model->index(0, 0)), true);

treeView_->setSortingEnabled(false);
treeView_->setSortingEnabled(0, true);
treeView_->setSortingEnabled(2, true);

/*
* Setup some buttons to manipulate the view and the model.
*/
WContainerWidget *wc =
this->addWidget(cpp14::make_unique<WContainerWidget>());
WPushButton *b;
b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle row height"));
b->clicked().connect(this, &TreeViewExample::toggleRowHeight);
b->setToolTip("Toggles row height between 31px and 25px");
b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle stripes"));
b->clicked().connect(this, &TreeViewExample::toggleStripes);
b->setToolTip("Toggle alternating row colors");
b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle root"));
b->clicked().connect(this, &TreeViewExample::toggleRoot);
b->setToolTip("Toggles root item between all and the first continent.");

b = wc->addWidget(cpp14::make_unique<WPushButton>("Add rows"));
b->clicked().connect(this, &TreeViewExample::addRows);
b->setToolTip("Adds some cities to Belgium");

b = wc->addWidget(cpp14::make_unique<WPushButton>("Show"));
b->clicked().connect(panel, &WPanel::show);
}

std::shared_ptr<WStandardItemModel> TreeViewExample::createModel(bool useInternalPath)
{
/*
* Setup a model.
*
* We use the standard item model, which is a general model
* suitable for hierarchical (tree-like) data, but stores all data
* in memory.
*/
auto result = std::make_shared<WStandardItemModel>(0, 4);

/*
* Headers ...
*/
result->setHeaderData(0, Orientation::Horizontal, std::string("Places"));
result->setHeaderData(1, Orientation::Horizontal, std::string("Weather"));
result->setHeaderData(2, Orientation::Horizontal, std::string("Drink"));
result->setHeaderData(3, Orientation::Horizontal, std::string("Visited"));
/*
* ... and data
*/
std::unique_ptr<WStandardItem> continent, country;
WStandardItem *continentPtr, *countryPtr;

continent = continentItem("Europe");
continentPtr = continent.get();
result->appendRow(std::move(continent));

country = countryItem("Belgium", "be");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer",
useInternalPath, true));
countryPtr->appendRow(cityItems("Leuven", Rain, "Beer",
useInternalPath, true));
country = countryItem("France", "fr");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Paris", Cloud, "Wine",
useInternalPath, true));
countryPtr->appendRow(cityItems("Bordeaux", SunCloud, "Bordeaux wine",
useInternalPath, false));
country = countryItem("Spain", "sp");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Barcelona", Sun, "Cava",
useInternalPath, true));
countryPtr->appendRow(cityItems("Madrid", Sun, "San Miguel",
useInternalPath, false));
continent = continentItem("Africa");
continentPtr = continent.get();
result->appendRow(std::move(continent));
country = countryItem("Morocco (المغرب)", "ma");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Casablanca", Sun, "Tea",
useInternalPath, false));

return result;
}

std::unique_ptr<WStandardItem> TreeViewExample::continentItem(const std::string& continent)
{
std::unique_ptr<WStandardItem> result
= cpp14::make_unique<WStandardItem>(continent);
result->setColumnCount(4);
return result;
}

std::unique_ptr<WStandardItem> TreeViewExample::countryItem(const std::string& country,
const std::string& code)
{
std::unique_ptr<WStandardItem> result
= cpp14::make_unique<WStandardItem>(WString(country));
result->setIcon("icons/flag_" + code + ".png");
return result;
}

std::vector<std::unique_ptr<WStandardItem>>
TreeViewExample::cityItems(const std::string& city,
WeatherIcon weather,
const std::string& drink,
bool useInternalPath, bool visited)
{
std::vector<std::unique_ptr<WStandardItem>> result;
std::unique_ptr<WStandardItem> item;
// column 0: country
item = cpp14::make_unique<WStandardItem>(WString(city));
result.push_back(std::move(item));
// column 1: weather
item = cpp14::make_unique<WStandardItem>();
item->setIcon(std::string("icons/") + weatherIcons[weather]);
result.push_back(std::move(item));
// column 2: drink
item = cpp14::make_unique<WStandardItem>(drink);
if (useInternalPath)
item->setLink(WLink(LinkType::InternalPath, "/drinks/" + drink));
result.push_back(std::move(item));
// column 3: visited
item = cpp14::make_unique<WStandardItem>();
item->setCheckable(true);
item->setChecked(visited);
result.push_back(std::move(item));
return result;
}

void TreeViewExample::toggleRowHeight()
{
if (treeView_->rowHeight() == WLength(31))
treeView_->setRowHeight(25);
else
treeView_->setRowHeight(31);
}

void TreeViewExample::toggleStripes()
{
treeView_->setAlternatingRowColors(!treeView_->alternatingRowColors());
}

void TreeViewExample::toggleRoot()
{
if (treeView_->rootIndex() == WModelIndex())
treeView_->setRootIndex(model_->index(0, 0));
else
treeView_->setRootIndex(WModelIndex());
}

void TreeViewExample::addRows()
{
static int COUNT = 10;

for (int i = 0; i < COUNT; ++i) {
std::string cityName = "City "
+ asString(belgium_->rowCount() + 1).toUTF8();
bool useInternalPath = false;
belgium_->appendRow(cityItems(cityName, Storm, "Juice",
useInternalPath, false));
}

treeView_->scrollTo(belgium_->child(belgium_->rowCount() -COUNT )->index(),
ScrollHint::PositionAtTop);
}
(1-1/4)