|
#include <Wt/WApplication>
|
|
#include <Wt/WContainerWidget>
|
|
#include <Wt/WVBoxLayout>
|
|
#include <Wt/WAbstractItemModel>
|
|
#include <Wt/WTableView>
|
|
|
|
using namespace Wt;
|
|
|
|
class GroupModel : public Wt::WAbstractItemModel
|
|
{
|
|
public:
|
|
GroupModel()
|
|
: WAbstractItemModel()
|
|
|
|
, groups_()
|
|
{
|
|
groups_.push_back(WString::fromUTF8("Group x"));
|
|
groups_.push_back(WString::fromUTF8("Group y"));
|
|
groups_.push_back(WString::fromUTF8("Group z"));
|
|
}
|
|
// WAbstractItemModel methods
|
|
boost::any headerData (int section, Orientation orientation, int role) const
|
|
{
|
|
switch(role)
|
|
{
|
|
case DisplayRole:
|
|
switch(section)
|
|
{
|
|
case 0:
|
|
return boost::any(WString::fromUTF8("Groups"));
|
|
}
|
|
}
|
|
return boost::any();
|
|
}
|
|
virtual Wt::WModelIndex index(int row, int col, const Wt::WModelIndex& = Wt::WModelIndex()) const
|
|
{
|
|
if(row >= 0 && row < (int)groups_.size())
|
|
return createIndex(row, col, (void*)0);
|
|
return WModelIndex();
|
|
}
|
|
virtual int columnCount(const Wt::WModelIndex& = Wt::WModelIndex()) const
|
|
{
|
|
return 1;
|
|
}
|
|
virtual int rowCount(const Wt::WModelIndex& = Wt::WModelIndex()) const
|
|
{
|
|
return groups_.size();
|
|
}
|
|
virtual Wt::WModelIndex parent(const Wt::WModelIndex&) const
|
|
{
|
|
return WModelIndex();
|
|
}
|
|
virtual Wt::WFlags<Wt::ItemFlag> flags(const Wt::WModelIndex &index) const
|
|
{
|
|
if(index.row() >= 0 && index.row() < (int) groups_.size())
|
|
{
|
|
return Wt::WFlags<Wt::ItemFlag>(ItemIsSelectable|ItemIsUserCheckable|ItemIsTristate);
|
|
}
|
|
return Wt::WFlags<Wt::ItemFlag>(ItemIsSelectable);
|
|
}
|
|
virtual bool setData(const Wt::WModelIndex &idx, const boost::any &value, int role)
|
|
{
|
|
if(!idx.isValid())
|
|
return false;
|
|
switch(role)
|
|
{
|
|
case Wt::CheckStateRole:
|
|
if(idx.row() >= 0 && idx.row() < (int) groups_.size())
|
|
{
|
|
if(value.type() == typeid(Wt::CheckState))
|
|
{
|
|
groups_[idx.row()] = groupStateName(boost::any_cast<Wt::CheckState>(value)) + groupName(groups_[idx.row()]);
|
|
fprintf(stderr, "setData(): groupname: %s (%d)\n", groups_[idx.row()].toUTF8().c_str(), boost::any_cast<Wt::CheckState>(value));
|
|
dataChanged().emit(index(idx.row(), 0), index(idx.row(), columnCount()-1));
|
|
} else if(value.type() == typeid(bool))
|
|
{
|
|
groups_[idx.row()] = groupStateName(boost::any_cast<bool>(value) ? Wt::Checked : Wt::Unchecked) + groupName(groups_[idx.row()]);
|
|
dataChanged().emit(index(idx.row(), 0), index(idx.row(), columnCount()-1));
|
|
}
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
virtual boost::any data(const Wt::WModelIndex& index, int role) const
|
|
{
|
|
if(!index.isValid() || index.row() < 0 || index.row() >= (int)groups_.size())
|
|
return boost::any();
|
|
switch(role)
|
|
{
|
|
case Wt::DisplayRole:
|
|
switch(groupState(groups_[index.row()]))
|
|
{
|
|
case Wt::Unchecked:
|
|
return boost::any(groupName(groups_[index.row()]) + WString::fromUTF8(" (unused)"));
|
|
case Wt::PartiallyChecked:
|
|
return boost::any(groupName(groups_[index.row()]) + WString::fromUTF8(" (disabled)"));
|
|
case Wt::Checked:
|
|
return boost::any(groupName(groups_[index.row()]));
|
|
}
|
|
break;
|
|
case Wt::CheckStateRole:
|
|
return boost::any(groupState(groups_[index.row()]));
|
|
default:
|
|
return boost::any();
|
|
}
|
|
return boost::any();
|
|
}
|
|
private:
|
|
Wt::CheckState groupState(const WString& group) const
|
|
{
|
|
if(!group.empty())
|
|
{
|
|
if(group.value()[0] == L'!')
|
|
return Wt::Unchecked;
|
|
else if(group.value()[0] == L'-')
|
|
return Wt::PartiallyChecked;
|
|
}
|
|
return Wt::Checked;
|
|
}
|
|
Wt::WString groupStateName(const Wt::CheckState state) const
|
|
{
|
|
switch(state)
|
|
{
|
|
case Wt::Unchecked:
|
|
return WString::fromUTF8("!");
|
|
case Wt::PartiallyChecked:
|
|
return WString::fromUTF8("-");
|
|
case Wt::Checked:
|
|
return WString::Empty;
|
|
}
|
|
return WString::Empty;
|
|
}
|
|
WString groupName(const WString& group) const
|
|
{
|
|
if(!group.empty() && (group.value()[0] == L'!' || group.value()[0] == L'-'))
|
|
return WString(group.value().substr(1));
|
|
return group;
|
|
}
|
|
|
|
private:
|
|
std::vector<WString> groups_;
|
|
};
|
|
|
|
class WtApp : public Wt::WApplication
|
|
{
|
|
public:
|
|
WtApp( const Wt::WEnvironment& env);
|
|
~WtApp() {}
|
|
|
|
private:
|
|
void vboxLayout();
|
|
|
|
private:
|
|
Wt::WTableView* view_;
|
|
GroupModel* model_;
|
|
};
|
|
|
|
WtApp::WtApp(const Wt::WEnvironment& env)
|
|
: Wt::WApplication(env)
|
|
, view_(new WTableView())
|
|
, model_(new GroupModel())
|
|
{
|
|
setCssTheme("polished");
|
|
view_->setModel(model_);
|
|
view_->setMinimumSize(WLength::Auto, 200);
|
|
|
|
vboxLayout();
|
|
}
|
|
|
|
void WtApp::vboxLayout()
|
|
{
|
|
Wt::WVBoxLayout* layout = new Wt::WVBoxLayout(root());
|
|
|
|
root()->setLayout(layout);
|
|
|
|
// row 0
|
|
layout->addWidget(view_, 1, Wt::AlignTop);
|
|
}
|
|
|
|
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
|
|
{
|
|
Wt::WApplication* myApplication = 0;
|
|
myApplication = new WtApp( env );
|
|
return myApplication;
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
Wt::WRun(argc, argv, &createApplication);
|
|
return 0;
|
|
}
|