Files
energy_storage/src/pv/PvTable.cpp

432 lines
13 KiB
C++
Raw Normal View History

#include "PvTable.h"
#include "PvStyle.h"
#include "pv/PvApp.h"
static const string STYLE_BKG =
"border-width:1 1 1 1px; border-style:outset solid; border-color:rgba(180,180,180,255);"
"background-color:rgba(80,80,80,0);";
//*********************************************************************************************************************
// PvTable
PvTable::PvTable(PARAM* p, int parent, int x, int y, int w, int row, Options& opts)
//: PvWidget(p, parent, PvRect(x, y, w, opts.item_height* row + (opts.show_header ? (opts.header_height) : 0))),
: PvObject(p), option_(opts), nRow_(row), nCol_(0)
{
// 计算表格的显示区域
int h = opts.row_height* row + (opts.show_header ? (opts.head_height) : 0);
rect_.set(x, y, w, h);
// 表格的主窗体QWidget设置样式无效
pvid_ = PvApp::widget(p, parent, x, y, w, h+1);
// 表格的背景色和边框样式
PvApp::label(p, pvid_, 0, 0, w, h+1, "", qss::QSS_TABLE);
vecHead_.resize(0);
vecRows_.resize(nRow_);
vecData_.resize(nRow_);
// 创建行高亮显示背景
for (int row = 0; row < nRow_; row++)
{
int y = item_posy(row);
string qss = (row % 2 != 0) ? qss::QSS_TABLE_ROW_0 : qss::QSS_TABLE_ROW_1;
int rowBkg = PvApp::label(p, pvid_, 1, y, rect_.w-2, option_.row_height, "", qss);
pvHide(p, rowBkg);
vecRows_[row].bkg = rowBkg;
}
}
void PvTable::addHead(string id, string text, int width, vector<pair<string, string>> mapping)
{
vecHead_.push_back(Head(id, text, width, mapping));
nCol_ = vecHead_.size();
if (width <= -1) { width = rect_.w-1 - posCol_; }
int col = nCol_ - 1;
// 创建表头的标签
if (option_.show_header)
{
vecHead_[col].pvid = PvApp::label(p, pvid_, posCol_, 0, width, option_.head_height, text, qss::QSS_TABLE_HEAD);
}
// 创建列的单元格
for (int row = 0; row < nRow_; ++row)
{
int y = item_posy(row);
int pvid = PvApp::label(p, pvid_, posCol_, y, width, option_.row_height, "", qss::QSS_TABLE_CELL);
vecRows_[row].vecCells.push_back(pvid);
PvApp::bind(p, MOUSE_OVER_EVENT, pvid, [=](string s) { highlight(row, (s == "1")); });
}
posCol_ += width;
}
void PvTable::addHead(vector<string> vec_text)
{
int colSize = vec_text.size();
int x = 0;
for (int i = 0; i < vec_text.size(); ++i)
{
int w = float(rect_.w-1) * float(i+1) / float(colSize);
string text = vec_text[i];
this->addHead(text, text, w-x);
x = w;
}
}
void PvTable::setRowVisible(int row, bool v)
{
if (row < 0 || row >= vecRows_.size())
{
return;
}
auto& rowItem = vecRows_[row];
if (rowItem.visible != v)
{
rowItem.visible = v;
rowItem.visible ? pvShow(p, rowItem.bkg) : pvHide(p, rowItem.bkg);
if (!v)
{
for (int col = 0; col<rowItem.vecCells.size(); ++col)
{
pvSetText(p, rowItem.vecCells[col], "");
}
}
}
}
void PvTable::highlight(int row, bool v)
{
string qss = ((row % 2 != 0) ? qss::QSS_TABLE_ROW_0 : qss::QSS_TABLE_ROW_1);
if (vecRows_.size() > 0 && row <= vecRows_.size())
{
if (v) { qss = "background-color:rgba(14,45,60,200);border:1px solid rgba(255,0,0,100);"; }
pvSetStyleSheet(p, vecRows_[row].bkg, qss.c_str());
}
}
void PvTable::addOperate(vector<string> vecOpt)
{
// 创建表头的标签
if (option_.show_header)
{
PvApp::label(p, pvid_, posCol_, 0, rect_.w - posCol_, option_.head_height, "操作", qss::QSS_TABLE_HEAD);
}
for (int row = 0; row < nRow_; ++row)
{
int y = item_posy(row);
int cellWidget = PvApp::label(p, pvid_, posCol_, y, rect_.w - posCol_, option_.row_height, "", qss::QSS_TABLE_CELL);
//PvInstance::bind_event(p, MOUSE_OVER_EVENT, btn_opt, [=](string s) { highlight(row, (s == "1")); });
vecOpt_.push_back({ cellWidget, vector<int>() });
auto& vec_opt_btn_ = vecOpt_.back().second;
int x = 5, w = 60;
for (int i = 0; i < vecOpt.size(); i++)
{
auto& title = vecOpt[i];
w = 20 + 15 * title.size() / 3;
int btn = PvApp::button(p, cellWidget, x, 4, w, 24, title, qss::button(14, "", "", "none; border-radius: 0px"));
PvApp::bind(p, PvEvent::BUTTON_EVENT, btn, [=](std::string) {
if (cbOperate_) { cbOperate_(row, 0, title); }
});
vec_opt_btn_.push_back(btn);
x += (w + 5);
}
pvHide(p, cellWidget);
}
}
void PvTable::setOperateCallback(CallbackTableOpt cb)
{
cbOperate_ = cb;
};
void PvTable::set_text(PARAM* p, int row, int col, string text, string style)
{
if (row < nRow_ && col < nCol_)
{
pvSetText(p, vecRows_[row].vecCells[col], text.c_str());
if (!style.empty())
{
int idx = row + 1;
if (idx % 2 != 0)
{
style = item_base_style_ + style;
}
else
{
style = item_base_style_ + style;
}
//style = "qproperty-alignment:AlignCenter;" + style + "}";
string s = "QLabel{" + style + "} QLabel:disabled{color:rgb(150,150,150)}";
pvSetStyleSheet(p, vecRows_[row].vecCells[col], s.c_str());
}
}
}
void PvTable::setRowData(int row, Fields& d)
{
if (row >= nRow_) { return; }
vecData_[row] = d;
for (int col = 0; col < vecHead_.size(); ++col)
{
auto& head = vecHead_[col];
string text = d.value(head.id);
text = head.getMapping(text);
pvSetText(p, vecRows_[row].vecCells[col], text.c_str());
}
setRowVisible(row, true);
this->setOperateVisible(row, d.size() > 0);
}
void PvTable::setRowData(int row, std::vector<std::string> vd)
{
if (row >= nRow_) { return; }
pvShow(p, vecRows_[row].bkg);
for (int col = 0; col < vecHead_.size(); ++col)
{
if (col < vd.size()) {
auto& head = vecHead_[col];
string text = head.getMapping(vd[col]);
pvSetText(p, vecRows_[row].vecCells[col], text.c_str());
}
}
setRowVisible(row, true);
this->setOperateVisible(row, vd.size() > 0);
}
Fields PvTable::getRowData(int row)
{
static Fields tmp;
return (row >= 0 && row < vecData_.size()) ? vecData_[row] : tmp;
}
void PvTable::mappingData(Fields& fields)
{
for (int i=0; i< vecHead_.size(); ++i)
{
auto& head = vecHead_[i];
if (fields.hasKey(head.id))
{
auto& val = fields.value(head.id);
val = head.getMapping(val);
}
}
}
void PvTable::set_border_visible(PARAM* p, bool v)
{
v ? pvShow(p, border_id_) : pvHide(p, border_id_);
}
int PvTable::item_posy(int row)
{
return option_.show_header ? row * option_.row_height + option_.head_height : row * option_.row_height;
}
void PvTable::add_col_button(PARAM* p, int col, string title, PvRect& rt, string style)
{
if (col >= nCol_)
{
return;
}
for (int row = 0; row < nRow_; ++row)
{
int id = PvApp::button(p, vecRows_[row].vecCells[col], rt.x, rt.y, rt.w, rt.h, title, style);
pvHide(p, id);
vec_col_item_btn_[row].push_back(id);
//PvInstance::bind_event(p, PvEvent::BUTTON_EVENT, id, [=](string s)
//{
// if (cb_operate_)
// {
// cb_operate_(row, col, title);
// }
//});
}
}
void PvTable::add_col_button(PARAM* p, int col, vector<string> vec_title)
{
int x = 5;
int w = 0;
for (int i = 0; i < vec_title.size(); i++)
{
auto& title = vec_title[i];
w = 20 + 20 * title.size() / 3;
this->add_col_button(p, col, title, PvRect(x, 3, w, 28), qss::button());
x += (w + 5);
}
}
void PvTable::setOperateVisible(int row, bool v, int id)
{
if (row < vecOpt_.size())
{
auto& vec_opt_btn = vecOpt_[row].second;
int pvid = id < 0 ? vecOpt_[row].first : ((id < vec_opt_btn.size()) ? vec_opt_btn[id] : PV_ID_NUL);
v ? pvShow(p, pvid) : pvHide(p, pvid);
}
}
int PvTable::border_id()
{
return border_id_;
}
int PvTable::rows()
{
return nRow_;
}
int PvTable::colums()
{
return nCol_;
}
vector<Fields> PvTable::data()
{
return vecData_;
}
PvTable::Head& PvTable::header(int col)
{
return vecHead_[col];
}
static const string STYLE_NORMAL =
"QPushButton { background-color:rgba(255,255,255,30);border-radius:0px;font:bold 16px ;color:white;border:1px solid #20a481;}"
"QPushButton:hover { background-color:rgba(32,164,128,255);color:white;}"
"QPushButton:pressed { border-width:3px 0 0 3px;border-style:inset;color:white;}"
"QPushButton:disabled { color: gray; border-color: gray; }";
static const string STYLE_ACTIVE =
"QPushButton { background-color:rgba(32,164,128,255);border-radius:0px;font:bold 16px ;color:white;border:1px solid #20a481;}"
"QPushButton:hover { background-color:rgba(32,164,128,255);color:white;}"
"QPushButton:pressed { border-width:3px 0 0 3px;border-style:inset;color:white;}"
"QPushButton:disabled { color: gray; border-color: gray; }";
PvPagination::PvPagination(PARAM* p, int parent, int x, int y, int n)
: PvObject(p)
{
pvid = PvApp::label(p, parent, x, y, 2*32 + 80, 30, "", "border: 0px solid gray;");
// 分页控件
btnPrev = PvApp::button(p, pvid, 0, 0, 30, 30, "<", STYLE_NORMAL);
for (int i = 0; i < n; i++)
{
int btn = PvApp::button(p, pvid, (i+1)*32, 0, 30, 30, std::to_string(i+1), STYLE_NORMAL);
pvHide(p, btn);
vecBtn.push_back({btn, i});
PvApp::bind(p, PvEvent::BUTTON_EVENT, btn, [=](string) { this->activePage(i, true); });
}
btnNext = PvApp::button(p, pvid, 32, 0, 30, 30, ">", STYLE_NORMAL);
labelInfo = PvApp::label(p, pvid, 2*32, 0, 80, 30, " 共0页", qss::label(14, "rgb(27, 220, 224)"));
pvSetEnabled(p, btnPrev, 0);
pvSetEnabled(p, btnNext, 0);
PvApp::bind(p, PvEvent::BUTTON_EVENT, btnPrev, [=](string e) { this->activePage(--pageIndex, true); });
PvApp::bind(p, PvEvent::BUTTON_EVENT, btnNext, [=](string e) { this->activePage(++pageIndex, true); });
}
void PvPagination::setPage(int index, int count)
{
pageIndex = index;
pageCount = count;
for (int i = 0; i < vecBtn.size(); ++i)
{
auto& btn = vecBtn[i];
auto btnid = btn.first;
int idx = i + 1;
if (idx > pageCount)
{
pvHide(p, btnid);
}
else
{
pvShow(p, btnid);
//if (pageCount > 7)
//{
// if (idx == 4)
// {
// idx = 0;
// }
// else if (idx > 4)
// {
// idx = pageCount - (7 - idx);
// }
//}
//btn.second = idx;
//string text = to_string(idx);
//if (text.empty() || text == "0")
//{
// text = "...";
// pvSetEnabled(p, btnid, false);
//}
////pvMove(p, btnid, x, y);
//pvSetText(p, btnid, text.c_str());
//if (idx == idx)
//{
// this->active_page_button(p, idx, pageIndex);
// pageIndex = idx;
//}
//x += (32);
}
}
int x = (count+1)*32;
pvMove(p, btnNext, x, 0);
pvMove(p, labelInfo, x+=32, 0);
pvSetText(p, labelInfo, ("" + std::to_string(count) + "").c_str());
pvResize(p, pvid, x += 81, 30);
this->activePage(pageIndex);
}
int PvPagination::page()
{
return pageIndex;
};
void PvPagination::activePage(int index, bool invoke)
{
if (pageCount == 0)
{
pageIndex = 0;
return;
}
pageIndex = index;
if (pageIndex < 0){ pageIndex = 0; }
if (pageIndex >= pageCount) { pageIndex = pageCount - 1; }
pvSetEnabled(p, btnPrev, pageIndex != 0);
pvSetEnabled(p, btnNext, (pageIndex != pageCount - 1));
if (btnActive != PV_ID_NUL) { pvSetStyleSheet(p, btnActive, STYLE_NORMAL.c_str()); }
btnActive = vecBtn[pageIndex].first;
pvSetStyleSheet(p, btnActive, STYLE_ACTIVE.c_str());
if (invoke)
{
if (callback) callback(pageIndex);
}
}
void PvPagination::setCallback(std::function<void(int index)> func)
{
callback = func;
}
PvPageTable::PvPageTable(PARAM* p, int parent, int x, int y, int w, int rows, PvTable::Options& opts)
//: PvWidget(p, parent, PvRect(x, y, w, opts.item_height* rows + (opts.show_header ? (opts.header_height) : 0)))
: PvObject(p)
{
int h = opts.row_height* rows + (opts.show_header ? (opts.head_height) : 0);
int pvid_ = PvApp::widget(p, parent, x, y, w, h);
table_ = make_shared<PvTable>(p, pvid_, 0, 0, w, rows, opts);
}
shared_ptr<PvTable> PvPageTable::getTable()
{
return table_;
}