| 
    
       #include <Wt/WServer>
 
     | 
  
  
     | 
    
       #include <Wt/WIOService>
 
     | 
  
  
     | 
    
       #include <Wt/WApplication>
 
     | 
  
  
     | 
    
       #include <Wt/WEnvironment>
 
     | 
  
  
     | 
    
       #include <Wt/WTabWidget>
 
     | 
  
  
     | 
    
       #include <Wt/WTableView>
 
     | 
  
  
     | 
    
       #include <Wt/WStandardItem>
 
     | 
  
  
     | 
    
       #include <Wt/WStandardItemModel>
 
     | 
  
  
     | 
    
       #include <Wt/WPushButton>
 
     | 
  
  
     | 
    
       #include <Wt/WLabel>
 
     | 
  
  
     | 
    
       #include <Wt/WLineEdit>
 
     | 
  
  
     | 
    
       #include <Wt/WBootstrapTheme>
 
     | 
  
  
     | 
    
       #include <Wt/WCssDecorationStyle>
 
     | 
  
  
     | 
    
       #include <Wt/WBreak>
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       struct RowData {
 
     | 
  
  
     | 
    
           RowData(){}
 
     | 
  
  
     | 
    
           RowData(const std::string &s, const std::string &d, const std::string &c, const std::string &u, unsigned int i, int t, int r) :
 
     | 
  
  
     | 
    
               cell1(s),
 
     | 
  
  
     | 
    
               cell2(d),
 
     | 
  
  
     | 
    
               cell3(c),
 
     | 
  
  
     | 
    
               cell4(u),
 
     | 
  
  
     | 
    
               value1(i), value2(t), value3(r)
 
     | 
  
  
     | 
    
           {}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           std::string cell1;
 
     | 
  
  
     | 
    
           std::string cell2;
 
     | 
  
  
     | 
    
           std::string cell3;
 
     | 
  
  
     | 
    
           std::string cell4;
 
     | 
  
  
     | 
    
           unsigned int value1;
 
     | 
  
  
     | 
    
           int value2;
 
     | 
  
  
     | 
    
           int value3;
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       class DataTable : public Wt::WContainerWidget
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       public:
 
     | 
  
  
     | 
    
           DataTable(WContainerWidget *parent = 0);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       private:
 
     | 
  
  
     | 
    
           Wt::WTableView *table;
 
     | 
  
  
     | 
    
           Wt::WStandardItemModel *model;
 
     | 
  
  
     | 
    
           Wt::WPushButton *first;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           Wt::WLineEdit *searchLineEdit;
 
     | 
  
  
     | 
    
           Wt::WPushButton *search;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           void initializeModel();
 
     | 
  
  
     | 
    
           void firstPage();
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           void insertData(const std::vector<RowData> &data);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           void searchText();
 
     | 
  
  
     | 
    
           void onRowSelected();
 
     | 
  
  
     | 
    
           void onClicked(const Wt::WModelIndex &index, const Wt::WMouseEvent &);
 
     | 
  
  
     | 
    
           void setText(const Wt::WString &t);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           enum { ROWS_PER_PAGE = 40 };
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       std::vector<RowData> dummyData(int n)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           std::vector<RowData> data;
 
     | 
  
  
     | 
    
           data.reserve(n);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           static const RowData le{"Cell 1", "Cell 2", "Cell 3", "Cell 4", 0, 0, 14};
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           for (int i = 0; i < n; ++i)
 
     | 
  
  
     | 
    
               data.push_back(le);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           return data;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       DataTable::DataTable(WContainerWidget *parent)
 
     | 
  
  
     | 
    
           : Wt::WContainerWidget(parent)
 
     | 
  
  
     | 
    
           , table(new Wt::WTableView)
 
     | 
  
  
     | 
    
           , model(0)
 
     | 
  
  
     | 
    
           , first(new Wt::WPushButton(" << "))
 
     | 
  
  
     | 
    
           , searchLineEdit(new Wt::WLineEdit)
 
     | 
  
  
     | 
    
           , search(new Wt::WPushButton("Search"))
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           first->clicked().connect(this, &DataTable::firstPage);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           search->clicked().connect(this, &DataTable::searchText);
 
     | 
  
  
     | 
    
           searchLineEdit->enterPressed().connect(this, &DataTable::searchText);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           initializeModel();
 
     | 
  
  
     | 
    
           table->setMinimumSize(850, Wt::WLength::Auto);
 
     | 
  
  
     | 
    
           table->setModel(model);
 
     | 
  
  
     | 
    
           table->setColumnWidth(4, 240);
 
     | 
  
  
     | 
    
           table->setHeaderClickSortEnabled(true);
 
     | 
  
  
     | 
    
           table->setSelectionMode(Wt::SingleSelection);
 
     | 
  
  
     | 
    
           table->setSelectionBehavior(Wt::SelectRows);
 
     | 
  
  
     | 
    
           table->clicked().connect(this, &DataTable::onClicked);
 
     | 
  
  
     | 
    
           table->setAlternatingRowColors(true);
 
     | 
  
  
     | 
    
           table->decorationStyle().setBorder(Wt::WBorder(), Wt::All);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           auto form = new Wt::WContainerWidget;
 
     | 
  
  
     | 
    
           form->setStyleClass("form-horizontal");
 
     | 
  
  
     | 
    
           auto controlGroup = new Wt::WContainerWidget;
 
     | 
  
  
     | 
    
           controlGroup->setStyleClass("control-group");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           controlGroup->addWidget(first);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           controlGroup->addWidget(searchLineEdit);
 
     | 
  
  
     | 
    
           controlGroup->addWidget(search);
 
     | 
  
  
     | 
    
           form->addWidget(controlGroup);
 
     | 
  
  
     | 
    
           addWidget(form);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           addWidget(table);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           setContentAlignment(Wt::AlignLeft);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           firstPage();
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::initializeModel()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           if (model == 0) {
 
     | 
  
  
     | 
    
               model = new Wt::WStandardItemModel(0, 5, this);
 
     | 
  
  
     | 
    
               std::vector<std::string> headerData;
 
     | 
  
  
     | 
    
               headerData.push_back(std::string("Title 1"));
 
     | 
  
  
     | 
    
               headerData.push_back(std::string("Title 2"));
 
     | 
  
  
     | 
    
               headerData.push_back(std::string("Title 3"));
 
     | 
  
  
     | 
    
               headerData.push_back(std::string("Title 4"));
 
     | 
  
  
     | 
    
               headerData.push_back(std::string("Title 5"));
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
               for (std::vector<std::string>::size_type i = 0; i < headerData.size(); ++i)
 
     | 
  
  
     | 
    
                   model->setHeaderData(i, boost::any(headerData.at(i)));
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::firstPage()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           searchLineEdit->setText(Wt::WString::Empty);
 
     | 
  
  
     | 
    
           insertData(dummyData(ROWS_PER_PAGE));
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::insertData(const std::vector<RowData> &data)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           model->removeRows(0, model->rowCount());
 
     | 
  
  
     | 
    
           for (std::vector<RowData>::size_type i = 0; i < data.size(); ++i) {
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
               const RowData &e = data.at(i);
 
     | 
  
  
     | 
    
               std::vector<Wt::WStandardItem*> items;
 
     | 
  
  
     | 
    
               items.reserve(5);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
               items.push_back(new Wt::WStandardItem(Wt::WString(e.cell1)));
 
     | 
  
  
     | 
    
               items.push_back(new Wt::WStandardItem(Wt::WString(e.cell2)));
 
     | 
  
  
     | 
    
               items.push_back(new Wt::WStandardItem(Wt::WString(e.cell3)));
 
     | 
  
  
     | 
    
               items.push_back(new Wt::WStandardItem(Wt::WString(e.cell4)));
 
     | 
  
  
     | 
    
               items.push_back(new Wt::WStandardItem(Wt::WString("{1}:{2}").arg(e.value2).arg(e.value3)));
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
               model->appendRow(items);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::searchText()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           insertData(dummyData(1000));
 
     | 
  
  
     | 
    
           first->setEnabled(true);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::onRowSelected()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           Wt::WModelIndexSet indexes = table->selectedIndexes();
 
     | 
  
  
     | 
    
           if (!indexes.empty()) {
 
     | 
  
  
     | 
    
               Wt::WModelIndex i = *indexes.begin();
 
     | 
  
  
     | 
    
               const Wt::WString sn = model->item(i.row(), i.column())->text();
 
     | 
  
  
     | 
    
               searchLineEdit->setText(sn);
 
     | 
  
  
     | 
    
               searchLineEdit->setFocus();
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::onClicked(const Wt::WModelIndex &index, const Wt::WMouseEvent &)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           const Wt::WString t = model->item(index.row(), 0)->text();
 
     | 
  
  
     | 
    
           setText(t);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void DataTable::setText(const Wt::WString &t)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           if (!t.empty()) {
 
     | 
  
  
     | 
    
               searchLineEdit->setText(t);
 
     | 
  
  
     | 
    
               searchLineEdit->setFocus();
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       class Application : public Wt::WApplication
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       public:
 
     | 
  
  
     | 
    
           Application(const Wt::WEnvironment &env)
 
     | 
  
  
     | 
    
               : Wt::WApplication(env)
 
     | 
  
  
     | 
    
               , tabs(0)
 
     | 
  
  
     | 
    
               , dataTable(0)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
               addMetaHeader(Wt::MetaName,"viewport", "width=device-width, initial-scale=1");
 
     | 
  
  
     | 
    
               Wt::WBootstrapTheme *theme = new Wt::WBootstrapTheme();
 
     | 
  
  
     | 
    
               theme->setVersion(Wt::WBootstrapTheme::Version2);
 
     | 
  
  
     | 
    
               theme->setResponsive(true);
 
     | 
  
  
     | 
    
               setTheme(theme);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
               root()->addStyleClass("container");
 
     | 
  
  
     | 
    
               loadData();
 
     | 
  
  
     | 
    
               enableUpdates();
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           void update()
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
               delete tabs->parent();
 
     | 
  
  
     | 
    
               tabs = 0;
 
     | 
  
  
     | 
    
               dataTable = 0;
 
     | 
  
  
     | 
    
               loadData();
 
     | 
  
  
     | 
    
               triggerUpdate();
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       private:
 
     | 
  
  
     | 
    
           Wt::WTabWidget *tabs;
 
     | 
  
  
     | 
    
           DataTable *dataTable;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           void loadData()
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
               auto *c = new Wt::WContainerWidget(root());
 
     | 
  
  
     | 
    
               tabs = new Wt::WTabWidget(c);
 
     | 
  
  
     | 
    
               tabs->setMaximumSize(850, Wt::WLength::Auto);
 
     | 
  
  
     | 
    
               dataTable = new DataTable;
 
     | 
  
  
     | 
    
               tabs->addTab(dataTable, Wt::WString("Tab"));
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       Wt::WApplication *createApplication(const Wt::WEnvironment& env)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           return new Application(env);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       int main(int argc, char **argv)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           Wt::WRun(argc, argv, createApplication);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     |