#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> 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 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 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 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() }); 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 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 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 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 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 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(p, pvid_, 0, 0, w, rows, opts); } shared_ptr PvPageTable::getTable() { return table_; }