mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-27 18:59:26 +08:00
476 lines
11 KiB
C++
476 lines
11 KiB
C++
|
|
#include "PvTable.h"
|
|||
|
|
#include "PvStyle.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_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_TABLE_ROW_0 : 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_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_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_TABLE_ROW_0 : 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_TABLE_HEAD);
|
|||
|
|
}
|
|||
|
|
for (int row = 0; row < nRow_; ++row)
|
|||
|
|
{
|
|||
|
|
int y = item_posy(row);
|
|||
|
|
int btn_opt = PvApp::label(p, pvid_, posCol_, y, rect_.w - posCol_, option_.row_height, "", QSS_TABLE_CELL);
|
|||
|
|
//PvInstance::bind_event(p, MOUSE_OVER_EVENT, btn_opt, [=](string s) { highlight(row, (s == "1")); });
|
|||
|
|
vecOpt_.push_back({ btn_opt, 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, btn_opt, x, 4, w, 24, title, QSS_TABLE_BTN_VIEW);
|
|||
|
|
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, btn_opt);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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, DataFields& d)
|
|||
|
|
{
|
|||
|
|
if (row >= nRow_) { return; }
|
|||
|
|
|
|||
|
|
vecData_[row] = d;
|
|||
|
|
for (int col = 0; col < vecHead_.size(); ++col)
|
|||
|
|
{
|
|||
|
|
auto& head = vecHead_[col];
|
|||
|
|
string text = d.getStr(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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
DataFields& PvTable::getRowdata(int row)
|
|||
|
|
{
|
|||
|
|
static DataFields tmp;
|
|||
|
|
return (row >= 0 && row < vecData_.size()) ? vecData_[row] : tmp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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::set_item_btn_callback(CallbackTableOpt cb)
|
|||
|
|
//{
|
|||
|
|
// //cb_opt_ = cb;
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
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);
|
|||
|
|
// }
|
|||
|
|
//});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string GetTableItemButtonStyle(string title)
|
|||
|
|
{
|
|||
|
|
static unordered_map<string, string> map_style =
|
|||
|
|
{
|
|||
|
|
//{PV::OPT_NEW, PvStyle::BTN_NEW},
|
|||
|
|
//{PV::OPT_EDIT, PvStyle::BTN_EDIT},
|
|||
|
|
//{PV::OPT_DEL, PvStyle::BTN_DELETE}
|
|||
|
|
};
|
|||
|
|
string style = map_style[title];
|
|||
|
|
if (style.empty())
|
|||
|
|
{
|
|||
|
|
style = BTN_EDIT;
|
|||
|
|
}
|
|||
|
|
return style;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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), BTN_EDIT);
|
|||
|
|
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<DataFields> 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;}";
|
|||
|
|
|
|||
|
|
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;}";
|
|||
|
|
|
|||
|
|
|
|||
|
|
PvPagination::PvPagination(PARAM* p, int parent, const PvRect& rt)
|
|||
|
|
: PvObject(p)
|
|||
|
|
{
|
|||
|
|
pvid_ = PvApp::label(p, parent, rt.x, rt.y, rt.w, rt.h, "", "");
|
|||
|
|
// 分页控件
|
|||
|
|
int x = 0;
|
|||
|
|
int y = 0;
|
|||
|
|
btn_prev_ = PvApp::button(p, pvid_, x, y, 30, 30, "<", STYLE_NORMAL);
|
|||
|
|
for (int i = 1; i <= 7; i++)
|
|||
|
|
{
|
|||
|
|
int id = PvApp::button(p, pvid_, x += 32, y, 30, 30, std::to_string(i), STYLE_NORMAL);
|
|||
|
|
vec_btn_page_.push_back({id, 0});
|
|||
|
|
//PvInstance::bind_event(p, PvEvent::BUTTON_EVENT, id, [=](string s) { this->on_click_page(id); });
|
|||
|
|
}
|
|||
|
|
btn_next_ = PvApp::button(p, pvid_, x += 32, y, 30, 30, ">", STYLE_NORMAL);
|
|||
|
|
|
|||
|
|
//PvInstance::bind_event(p, PvEvent::BUTTON_EVENT, btn_prev_, [=](string e) { this->on_click_prev(); });
|
|||
|
|
//PvInstance::bind_event(p, PvEvent::BUTTON_EVENT, btn_next_, [=](string e) { this->on_click_next(); });
|
|||
|
|
|
|||
|
|
this->set_page(0, 0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PvPagination::set_page(int page_id, int max_page)
|
|||
|
|
{
|
|||
|
|
this->active_page_button(p, page_id, page_id_);
|
|||
|
|
|
|||
|
|
page_id_ = page_id;
|
|||
|
|
page_count_ = max_page;
|
|||
|
|
|
|||
|
|
int x = 32;
|
|||
|
|
int y = 0;// table_->rect().h + 16;
|
|||
|
|
for (int i = 0; i < vec_btn_page_.size(); ++i)
|
|||
|
|
{
|
|||
|
|
auto& btn_info = vec_btn_page_[i];
|
|||
|
|
auto btnid = btn_info.first;
|
|||
|
|
int idx = i + 1;
|
|||
|
|
if (idx > page_count_)
|
|||
|
|
{
|
|||
|
|
pvHide(p, btnid);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pvShow(p, btnid);
|
|||
|
|
if (page_count_ > 7)
|
|||
|
|
{
|
|||
|
|
if (idx == 4)
|
|||
|
|
{
|
|||
|
|
idx = 0;
|
|||
|
|
}
|
|||
|
|
else if (idx > 4)
|
|||
|
|
{
|
|||
|
|
idx = page_count_ - (7 - idx);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
btn_info.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 (page_id == idx)
|
|||
|
|
{
|
|||
|
|
this->active_page_button(p, page_id, page_id_);
|
|||
|
|
page_id_ = page_id;
|
|||
|
|
}
|
|||
|
|
x += (32);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
pvMove(p, btn_next_, x, y);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int PvPagination::pageid()
|
|||
|
|
{
|
|||
|
|
return page_id_;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
void PvPagination::active_page_button(PARAM* p, int new_pageid, int old_pageid)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < vec_btn_page_.size(); i++)
|
|||
|
|
{
|
|||
|
|
auto& item = vec_btn_page_[i];
|
|||
|
|
if (item.second != 0)
|
|||
|
|
{
|
|||
|
|
if (item.second == old_pageid)
|
|||
|
|
{
|
|||
|
|
pvSetStyleSheet(p, item.first, STYLE_NORMAL.c_str());
|
|||
|
|
}
|
|||
|
|
if (item.second == new_pageid)
|
|||
|
|
{
|
|||
|
|
pvSetStyleSheet(p, item.first, STYLE_ACTIVE.c_str());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PvPagination::set_goto_page_callback(std::function<void(int pageidx)> cb)
|
|||
|
|
{
|
|||
|
|
cb_goto_ = cb;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PvPagination::on_click_page(int btnid)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < vec_btn_page_.size(); ++i)
|
|||
|
|
{
|
|||
|
|
auto& item = vec_btn_page_[i];
|
|||
|
|
if (btnid == item.first)
|
|||
|
|
{
|
|||
|
|
int page_id = item.second;
|
|||
|
|
if (cb_goto_) { cb_goto_(page_id); }
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PvPagination::on_click_prev()
|
|||
|
|
{
|
|||
|
|
if (page_id_ <= 1)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (cb_goto_)
|
|||
|
|
{
|
|||
|
|
cb_goto_(page_id_ - 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PvPagination::on_click_next()
|
|||
|
|
{
|
|||
|
|
if (page_id_ >= page_count_)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (cb_goto_)
|
|||
|
|
{
|
|||
|
|
cb_goto_(page_id_ + 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
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_;
|
|||
|
|
}
|