Project

General

Profile

Bug #1038 » mir_wcustomtableview.h

Łukasz Matuszewski, 11/18/2011 10:59 AM

 
#ifndef _MIR_WCUSTOMTABLEVIEW_H_
#define _MIR_WCUSTOMTABLEVIEW_H_
/*
* Copyright (c) 2011,
* Technical University Of Gdansk,
* Faculty of Electronics, Telecommunications and Informatics,
* Multimedia Systems Department
* and/or its affiliates. All rights reserved.
*/
#include <Wt/WEnvironment>
#include <Wt/WContainerWidget>
#include <Wt/WCompositeWidget>
#include <Wt/WAbstractItemModel>
#include <Wt/WTableView>
#include <Wt/WAnchor>
#include <Wt/WPushButton>
#include <Wt/WCheckBox>
#include <Wt/WComboBox>
#include <Wt/WLink>
#include <Wt/Dbo/Dbo>
#include <Wt/Dbo/QueryModel>
#include <Wt/WEvent>
#include <Wt/WHBoxLayout>
#include <Wt/WSlider>
#include <Wt/WEvent>

#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>

#include <vector>

#include "utils/mir_trkeys.h"
#include "utils/mir_cssclasses.h"
#include "widgets/mir_wcustomtableviewpushbutton.h"
#include "mir_databasemodule.h"
#include "resources/mir_sp_paramselresource.h"

namespace SyNaT
{
namespace MIR
{
using namespace Wt;
using namespace std;
namespace dbo = Wt::Dbo;

template <class Result>
class WCustomTableView;

template <class Result>
class WCustomTableViewImpl : public WContainerWidget
{
friend class WCustomTableViewPushButton<Result>;

public:

WCustomTableViewImpl(DatabaseModule *dm, dbo::Session *session, bool likeStatement = false, WCustomTableView<Result> *ctv = 0)
: m_customTableView(ctv), m_checkable(false)
, m_current_page(0), m_nav_bar_created(false), m_num_of_pages_in_nav_bar(1)
, m_first_page_in_nav_bar(0), m_last_page_in_nav_bar(m_num_of_pages_in_nav_bar-1)
, m_dm(dm), m_session(session), m_pref_num_of_pages_in_nav_bar(4)
{
WContainerWidget *options_bar = new WContainerWidget();
this->addWidget(options_bar);
options_bar->setClearSides(Left | Right);
// WPushButton *wpb = new WPushButton(tr(MIR_WCTV_SAVE_SEL), options_bar);
// wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
// new WText("&nbsp;&nbsp;&nbsp;", XHTMLText, options_bar);
WAnchor *ar = new WAnchor(WLink(new SP::ParamsSelResource(this->m_dm)), tr(MIR_WCTV_EXPORT_SEL_PARS), options_bar);
ar->setTarget(TargetNewWindow);
options_bar = new WContainerWidget();
this->addWidget(options_bar);
options_bar->setClearSides(Left | Right);
//this->m_txt = new WText(tr(MIR_TABLE_EXP_SEARCH).arg(WString::Empty), options_bar);
//this->m_txt->disable();
this->m_sle = new WLineEdit(options_bar);
this->m_sle->setTextSize(30);

this->m_scb = new WComboBox(options_bar);

//this->m_sle->disable();
//if (likeStatement)
//{
// this->m_wcb = new WCheckBox(tr(MIR_TABLE_EXP_LIKE), options_bar);
// this->m_wcb->disable();
//}

this->m_wpb = new WPushButton(tr(MIR_WCTV_APPLY_SEARCH), options_bar);
this->m_show_only_selected = new WCheckBox(tr(MIR_WCTV_SHOW_ONLY_SELECTED), options_bar);

this->m_txt_selected = new WText(tr(MIR_WCTV_SELECTED), options_bar);
this->m_txt_all_displayed = new WText(tr(MIR_WCTV_ALL_DISPLAYED), options_bar);

options_bar = new WContainerWidget();
this->addWidget(options_bar);
options_bar->setClearSides(Left | Right);
WHBoxLayout *layout = new WHBoxLayout();
this->m_selectAll = new WPushButton(tr(MIR_WCTV_SELECT_ALL_FILTERED));
layout->addWidget(this->m_selectAll);
this->m_selectAll->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
this->m_inverseSelection = new WPushButton(tr(MIR_WCTV_INVERSE_SELECTION));
layout->addWidget(this->m_inverseSelection);
this->m_inverseSelection->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
// new WText("&nbsp;&nbsp;&nbsp;", XHTMLText, options_bar);
this->m_unselectAll = new WPushButton(tr(MIR_WCTV_UNSELECT_ALL_FILTERED));
layout->addWidget(this->m_unselectAll);
this->m_unselectAll->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
options_bar->setLayout(layout, AlignTop | AlignJustify);
options_bar = new WContainerWidget();
options_bar->setClearSides(Left | Right);
layout = new WHBoxLayout();
this->m_wtv = new WTableView();
layout->addWidget(this->m_wtv);
this->m_slider = new WSlider(Vertical);
this->m_slider->setTickPosition(WSlider::TicksRight);
layout->addWidget(this->m_slider);
options_bar->setLayout(layout, AlignTop | AlignJustify);
this->addWidget(options_bar);
this->m_page_nav_bar = new WContainerWidget();
this->addWidget(this->m_page_nav_bar);
this->m_page_nav_bar->setClearSides(Left | Right);
}

virtual ~WCustomTableViewImpl()
{
}

WText &selectedText()
{
return *(this->m_txt_selected);
}

WText &displayedAllText()
{
return *(this->m_txt_all_displayed);
}

WLineEdit &searchLineEdit()
{
return *(this->m_sle);
}

WComboBox &searchComboBox()
{
return *(this->m_scb);
}

WPushButton &searchPushButton()
{
return *(this->m_wpb);
}

WCheckBox &showOnlySelectedCheckBox()
{
return *(this->m_show_only_selected);
}

//WCheckBox &searchCheckBoxLike()
//{
// return *(this->m_wcb);
//}

WPushButton &selectAllPushButton()
{
return *(this->m_selectAll);
}

WPushButton &inverseSelection()
{
return *(this->m_inverseSelection);
}

WPushButton &unselectAllPushButton()
{
return *(this->m_unselectAll);
}

WSlider &slider()
{
return *(this->m_slider);
}

int update_slider()
{
int max = this->pageCount() + (this->pageCountReminder() > 0 ? -1 : -2);
if (max < 0) max = 1;
this->m_slider->setRange(0, max);
int tickInterval = (int) (this->height().value() / max);

if (tickInterval < 10)
tickInterval = (int) ((10 * max) / this->height().value());

if (tickInterval < 1)
tickInterval = max;
this->m_slider->setTickInterval(tickInterval);
return max;
}

virtual void load()
{
if (!this->loaded())
{
this->m_first_page_in_nav_bar = 0;
this->m_page_nav_bar->setLayout(this->create_page_nav_bar(), AlignTop | AlignJustify);
this->m_slider->setValue(this->update_slider());

this->m_slider->sliderMoved().connect(this, &WCustomTableViewImpl::slt_sliderMoved);

this->m_nav_bar_created = true;
}
this->WContainerWidget::load();
}

int rowsPerPage() const
{
return this->m_rows_per_page;
}

void setRowsPerPage(const int rows)
{
this->m_rows_per_page = rows;
}

void slt_sliderMoved(int page_clicked)
{
bool nbnu = false;
// if (this->pageCount() >= page_clicked)
// {
page_clicked = (int) (((this->m_slider->maximum() - page_clicked) / (this->m_slider->maximum() * 1.0)) * (this->pageCount() - 1));

if (this->m_current_page != page_clicked)
{
if (page_clicked <= this->pageCount())
this->scrollTo(
this->model()
->index(page_clicked * this->rowsPerPage(), 0), WTableView::PositionAtTop);
this->m_first_page_in_nav_bar = page_clicked;
this->m_last_page_in_nav_bar = page_clicked + this->m_num_of_pages_in_nav_bar - 1;
if ((this->m_first_page_in_nav_bar + this->m_num_of_pages_in_nav_bar) > this->pageCount())
{
this->m_first_page_in_nav_bar = this->pageCount() - this->m_num_of_pages_in_nav_bar;
this->m_last_page_in_nav_bar = this->pageCount();
}
this->m_current_page = page_clicked;

nbnu = true;
}
// }
// else
// {
// this->update_slider();
// this->m_slider->setValue(this->m_slider->maximum());
// }
this->update_page_nav_bar(nbnu);
}

dbo::QueryModel<Result> *model() const
{
return dynamic_cast<dbo::QueryModel<Result> *>(this->m_wtv->model());
}

void setModel(dbo::QueryModel<Result> *model)
{

if (model)
model->layoutChanged().connect(this, &WCustomTableViewImpl::slt_modelLayoutChanged);
this->m_wtv->setModel(model);
int row_count = this->model()->rowCount();
this->m_page_count_reminder = (row_count > this->rowsPerPage()) ? row_count % this->rowsPerPage() : 0;
this->m_page_count = (int) (((row_count * 1.0)/ (this->rowsPerPage()) + ((this->m_page_count_reminder) > 0 ? 1 : 0)));
}

void slt_modelLayoutChanged()
{
//int sortColumn = this->sortColumn();
//if (sortColumn > -1)
//{
//WString headerName = boost::any_cast<WString>(this->model()->headerData(sortColumn));
//this->m_txt->setText(tr(MIR_TABLE_EXP_SEARCH).arg(headerName));
//this->m_txt->enable();
//this->m_sle->enable();
//this->m_wcb->enable();
//}
//else
//{
//this->m_txt->setText(tr(MIR_TABLE_EXP_SEARCH).arg(WString::Empty));
//this->m_txt->disable();
//this->m_sle->disable();
//this->m_wcb->disable();
//}
int row_count = this->model()->rowCount();
this->m_page_count_reminder = (row_count > this->rowsPerPage()) ? row_count % this->rowsPerPage() : 0;
this->m_page_count = (int) (((row_count * 1.0)/ (this->rowsPerPage()) + ((this->m_page_count_reminder) > 0 ? 1 : 0)));
}

void setSortingEnabled(int column, bool enabled)
{
this->m_wtv->setSortingEnabled(column, enabled);
}

virtual void setRowHeight(const WLength& rowHeight)
{
this->m_wtv->setRowHeight(rowHeight);
}

virtual void setColumnWidth(int column, const WLength& width)
{
this->m_wtv->setColumnWidth(column, width);
}

void sortByColumn(int column, SortOrder order)
{
this->m_wtv->sortByColumn(column, order);
}

virtual void setAlternatingRowColors(bool enable)
{
this->m_wtv->setAlternatingRowColors(enable);
}

void setItemDelegateForColumn(int column, WAbstractItemDelegate *delegate)
{
this->m_wtv->setItemDelegateForColumn(column, delegate);
}

virtual void setSelectable(bool selectable)
{
this->m_wtv->setSelectable(selectable);
}

virtual void setCheckable(const bool checkable)
{
this->m_checkable = checkable;
}

virtual void resize(const int& widthPx, const int& heightPx)
{
this->WContainerWidget::resize(widthPx, heightPx);
this->m_wtv->resize(widthPx, heightPx-120);
this->m_slider->setHeight(heightPx-120);
}

virtual void resize(const WLength& width, const WLength& height)
{
this->WContainerWidget::resize(width, height);
}

virtual void resize_inner_table_view(const WLength& width, const WLength& height)
{
this->m_wtv->resize(width, height);
}

virtual void scrollTo(const WModelIndex& index,
Wt::WTableView::ScrollHint hint = Wt::WTableView::EnsureVisible)
{
this->m_wtv->scrollTo(index, hint);
}

virtual int pageCount() const
{
return this->m_page_count;//(this->model()->rowCount() / (this->rowsPerPage()));
}

virtual int pageCountReminder() const
{
return this->m_page_count_reminder;//(this->model()->rowCount() / (this->rowsPerPage()));
}



virtual int pageSize() const
{
return this->m_wtv->pageSize();
}

virtual void setPrefNumOfPagesInNavBar(int num_of_pages)
{
this->m_pref_num_of_pages_in_nav_bar = num_of_pages;
}

virtual int sortColumn()
{
return this->m_wtv->sortColumn();
}

virtual void refresh()
{
this->m_wtv->refresh();
}

void update_page_nav_bar(const bool navBarNeedUpdate = false)
{
int page_count = this->pageCount();
if (navBarNeedUpdate && this->m_nav_bar_created)
{
//if (page_count < this->m_first_page_in_nav_bar + this->m_pref_num_of_pages_in_nav_bar - 1)
if (page_count < this->m_first_page_in_nav_bar + this->m_num_of_pages_in_nav_bar - 1)
{
this->m_first_page_in_nav_bar = 0;
this->m_num_of_pages_in_nav_bar = page_count - this->m_first_page_in_nav_bar;
this->m_current_page = 0;
// this->model()->reload();
this->m_wtv
->scrollTo(
this->model()->index(0, 0), WTableView::PositionAtTop);
}
else
this->m_num_of_pages_in_nav_bar = this->m_pref_num_of_pages_in_nav_bar;

this->m_page_nav_bar->clear();
this->m_page_numbers.clear();
this->m_page_nav_bar->setLayout(this->create_page_nav_bar(), AlignTop | AlignJustify);
}
if ((this->m_page_numbers.size() > 0) && (this->m_page_numbers.at(0)->text().toUTF8() != boost::lexical_cast<string>(this->m_first_page_in_nav_bar + 1)))
{
int first_page_in_nav_bar = this->m_first_page_in_nav_bar;

BOOST_FOREACH(WCustomTableViewPushButton<Result> *b, this->m_page_numbers)
{
b->setText(boost::lexical_cast<string>(first_page_in_nav_bar++ + 1));
}
}
string current_page = boost::lexical_cast<string>(this->m_current_page + 1);
BOOST_FOREACH(WCustomTableViewPushButton<Result> *b, this->m_page_numbers)
{
if (b->text().toUTF8() == current_page)
{
b->setStyleClass(MIR_STRCAT3(MIR_CSS_PAGE_NAV_BUTTON," ",MIR_CSS_PAGE_NAV_BUTTON_SELECTED));
}
else
{
b->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
}
}

}

protected:

virtual WHBoxLayout *create_page_nav_bar()
{
WHBoxLayout *layout = new WHBoxLayout();
int page_count = this->pageCount();
if (page_count > this->m_pref_num_of_pages_in_nav_bar)
page_count = this->m_pref_num_of_pages_in_nav_bar;
this->m_num_of_pages_in_nav_bar = page_count;
if (this->pageCount() > 1)
{
WCustomTableViewPushButton<Result> *wpb = new WCustomTableViewPushButton<Result>(tr(MIR_WCTV_FIRST), this);
this->m_wpbFirst = wpb;
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_first_page_clicked);
wpb = new WCustomTableViewPushButton<Result>(tr(MIR_WCTV_PREV), this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_prev_page_clicked);
wpb = new WCustomTableViewPushButton<Result>("<", this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_prev_pages_clicked);

for(int i = this->m_first_page_in_nav_bar; i < this->m_first_page_in_nav_bar + page_count; i++)
{
wpb = new WCustomTableViewPushButton<Result>(boost::lexical_cast<string>(i+1), this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_page_clicked);
this->m_page_numbers.push_back(wpb);
}

this->m_last_page_in_nav_bar = this->m_first_page_in_nav_bar + page_count - 1;

wpb = new WCustomTableViewPushButton<Result>(">", this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_next_pages_clicked);
wpb = new WCustomTableViewPushButton<Result>(tr(MIR_WCTV_NEXT), this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_next_page_clicked);
wpb = new WCustomTableViewPushButton<Result>(tr(MIR_WCTV_LAST), this);
layout->addWidget(wpb);
wpb->setStyleClass(MIR_STRINGIFY(MIR_CSS_PAGE_NAV_BUTTON));
wpb->clicked().connect(wpb, &WCustomTableViewPushButton<Result>::slt_last_page_clicked);
}
this->update_page_nav_bar();
return layout;
}

private:
WTableView *m_wtv;

DatabaseModule *m_dm;

WContainerWidget *m_page_nav_bar;

WLineEdit *m_sle;

WComboBox *m_scb;

WText *m_txt_selected;

WText *m_txt_all_displayed;

WPushButton *m_wpb;

WCheckBox *m_show_only_selected;

//WCheckBox *m_wcb;

WPushButton *m_selectAll;

WPushButton *m_inverseSelection;

WPushButton *m_unselectAll;

WSlider *m_slider;

dbo::Session *m_session;

vector<WCustomTableViewPushButton<Result> *> m_page_numbers;

WCustomTableViewPushButton<Result> *m_wpbFirst;
bool m_checkable;

int m_first_page_in_nav_bar;

int m_last_page_in_nav_bar;

int m_current_page;

int m_num_of_pages_in_nav_bar;

int m_pref_num_of_pages_in_nav_bar;

int m_rows_per_page;

bool m_nav_bar_created;

int m_page_count;

int m_page_count_reminder;

WCustomTableView<Result> *m_customTableView;
};

template <class Result>
class WCustomTableView : public WCompositeWidget
{
public:
WCustomTableView(DatabaseModule *dm, dbo::Session *session, bool likeStatement = false, WContainerWidget *parent = 0)
: WCompositeWidget(parent)
{
impl_ = new WCustomTableViewImpl<Result>(dm, session, likeStatement, this);
setImplementation(impl_);
}

WCustomTableViewImpl<Result> *impl()
{
return this->impl_;
}

private:
WCustomTableViewImpl<Result> *impl_;
};

}
}
#endif /* _MIR_WCUSTOMTABLEVIEW_H_ */
(1-1/4)