|
#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(" ", 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(" ", 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_ */
|