Files
Renderive/Widget/component/Table/Base_Table_Model.cpp
T

318 lines
10 KiB
C++

#include "Base_Table_Model.h"
#include "Widget/base/Generate_Mock_Data.h"
#include "Renderive/base/global.h"
#include "Base_Info.h"
#include "Base_Table_Data.h"
namespace Psc {
struct Row_Info;
Pos get_pos(Base_Info** infos, int n, int space, int pos, int margin) {
int cur_line_pos = margin;
int last_i = 0;
for (int i = 0; i < n - 1; ++i) {
auto cur = infos[i];
if (cur->hide) {
continue;
}
int step = cur->len + space;
if (cur_line_pos + step > pos) {
return {i, cur_line_pos, pos - cur_line_pos};
}
cur_line_pos += step;
last_i = i;
}
return {std::max(0, n - 1), cur_line_pos, pos - cur_line_pos};
}
Base_Table_Model::Base_Table_Model() {}
Row_Info* Base_Table_Model::create_row_info(int h) {
return new Row_Info(h, "");
}
Col_Info* Base_Table_Model::create_col_info(int w) {
return new Col_Info(w, "");
}
// 核心位置计算
int Memory_Table_Model::cell_x(int index) {
if (index == 0)
return 0;
int ret = 0;
for (int i = 0; i < index; i++) {
auto cur = col_info_list[i];
if (cur->hide)
continue;
ret += cur->len + col_space;
}
return ret;
}
int Memory_Table_Model::cell_y(int index) {
if (index == 0)
return 0;
int ret = 0;
for (int i = 0; i < index; i++) {
auto cur = row_info_list[i];
if (cur->hide)
continue;
ret += cur->len + row_space;
}
return ret;
}
int Memory_Table_Model::row_span_len(int row, int row_span) {
int ret = -row_space;
for (int i = 0; i < row_span; i++) {
auto cur = row_info_list[row + i];
if (cur->hide)
continue;
ret += cur->len + row_space;
}
return ret;
}
int Memory_Table_Model::col_span_len(int col, int col_span) {
int ret = -col_space;
for (int i = 0; i < col_span; i++) {
auto cur = col_info_list[col + i];
if (cur->hide)
continue;
ret += cur->len + col_space;
}
return ret;
}
Pos Memory_Table_Model::get_col(int x) {
return get_pos((Base_Info**)col_info_list.data(), col_info_list.size(), col_space, x, 0);
}
Pos Memory_Table_Model::get_row(int y) {
return get_pos((Base_Info**)row_info_list.data(), row_info_list.size(), row_space, y, 0);
}
std::vector<std::vector<Base_Table_Data*>> exchange_row_col(const std::vector<std::vector<Base_Table_Data*>>& data) {
std::vector<std::vector<Base_Table_Data*>> ret;
int m = data.size();
int n = data.front().size();
for (int i = 0; i < n; ++i) {
std::vector<Base_Table_Data*> t;
for (int j = 0; j < m; ++j) {
t.push_back(data[j][i]);
}
ret.push_back(t);
}
return ret;
};
enum Cell_Type {
Merge_head,
Merge_Cell,
Normal
};
Cell_Type cell_type(const std::vector<std::vector<Base_Table_Data*>>& data, int col, int row) {
auto that = data[col][row];
if (that->parent != that)
return Merge_Cell;
if (data[col + 1][row]->parent == that)
return Merge_head;
if (data[col][row + 1]->parent == that)
return Merge_head;
return Normal;
}
Cell_Info Base_Table_Model::get_span(int xi, int yi) {
return Cell_Info(xi, yi, col_span_len(xi, 1), row_span_len(yi, 1));
}
Find_Ret Base_Table_Model::find_parent(Base_Table_Data* parent, int xi, int yi) {
return Find_Ret(xi, yi);
}
void Memory_Table_Model::split(int row, int col, int row_span, int col_span) {
for (int i = 0; i < col_span; ++i) {
for (int j = 0; j < row_span; ++j) {
auto cur = data[col + i][row + j];
cur->parent = cur;
}
}
}
void Memory_Table_Model::merge(int row, int col, int row_span, int col_span) {
auto start = data[col][row];
for (int i = 0; i < row_span; ++i) {
for (int j = 0; j < col_span; ++j) {
if (i == 0 && j == 0)
continue;
int cur_row = row + i;
int cur_col = col + j;
auto cur = data[cur_col][cur_row];
cur->parent = start;
}
}
}
// parent 是复刻他上一行的parent
bool Memory_Table_Model::insert_row(int pos, const std::vector<Row_Info*>& infos, const std::vector<std::vector<Base_Table_Data*>>& d, Edge_Expand_Type t) {
int col_num = col_info_list.size();
int insert_row_num = infos.size();
if (!d.empty() && d.front().size() != col_num) {
qDebug() << VAR_QSTR_2(d.front().size(), col_num) << " " << QLOG_POS;
return false;
}
// 行结构转列结构
auto insert_col_list = exchange_row_col(d);
for (int col = 0; col < col_num; ++col) {
Base_Table_Data* prev = nullptr;
Base_Table_Data* next = nullptr;
Base_Table_Data* par = nullptr;
int row_num = total_row();
if (pos - 1 > 0 && pos - 1 < row_num) {
prev = data[col][pos - 1];
}
if (pos < row_num) {
next = data[col][pos];
}
if (t == Edge_Expand_Type::Positive) {
if (prev && prev->parent != prev) {
par = prev->parent;
}
}
else if (t == Edge_Expand_Type::Negative) {
if (next && next->parent != next) {
par = next->parent;
}
}
else if (t == Edge_Expand_Type::None) {
if (next && prev && prev->parent == next->parent) {
par = prev->parent;
}
}
for (int j = 0; j < insert_row_num; ++j) {
auto cur = insert_col_list[col][j];
cur->parent = par ? par : cur;
}
data[col].insert(data[col].begin() + pos, insert_col_list[col].begin(), insert_col_list[col].end());
}
row_info_list.insert(row_info_list.begin() + pos, infos.begin(), infos.end());
return true;
}
bool Memory_Table_Model::insert_col(int pos, const std::vector<Col_Info*>& infos, const std::vector<std::vector<Base_Table_Data*>>& d, Edge_Expand_Type t) {
int row_num = row_info_list.size();
int insert_col_num = infos.size();
if (!d.empty() && d.front().size() != row_num) {
qDebug() << VAR_QSTR_2(d.front().size(), row_num) << " " << QLOG_POS;
return false;
}
for (int row = 0; row < row_num; ++row) {
Base_Table_Data* prev = nullptr;
Base_Table_Data* next = nullptr;
Base_Table_Data* par = nullptr;
int col_num = total_col();
if (pos - 1 > 0 && pos - 1 < col_num) {
prev = data[pos - 1][row];
}
if (pos < col_num) {
next = data[pos][row];
}
if (t == Edge_Expand_Type::Positive) {
if (prev && prev->parent != prev) {
par = prev->parent;
}
}
else if (t == Edge_Expand_Type::Negative) {
if (next && next->parent != next) {
par = next->parent;
}
}
else if (t == Edge_Expand_Type::None) {
if (next && prev && prev->parent == next->parent) {
par = prev->parent;
}
}
for (int col = 0; col < insert_col_num; ++col) {
auto cur = d[col][row];
cur->parent = par ? par : cur;
}
}
data.insert(data.begin() + pos, d.begin(), d.end());
col_info_list.insert(col_info_list.begin() + pos, infos.begin(), infos.end());
return true;
}
bool Memory_Table_Model::remove_row(int pos, int num) {
if (pos + num >= row_info_list.size()) {
qDebug() << VAR_QSTR_3(pos, num, row_info_list.size()) << " " << QLOG_POS;
return false;
}
for (auto& col : data) {
for (auto item = col.begin() + pos; item != col.begin() + pos + num; ++item)
delete *item;
col.erase(col.begin() + pos, col.begin() + pos + num);
}
for (int i = 0; i < num; ++i) {
delete row_info_list[pos + i];
}
row_info_list.erase(row_info_list.begin() + pos, row_info_list.begin() + pos + num);
return true;
}
bool Memory_Table_Model::remove_col(int pos, int num) {
if (pos + num >= col_info_list.size()) {
qDebug() << VAR_QSTR_3(pos, num, col_info_list.size()) << " " << QLOG_POS;
return false;
}
for (auto column = data.begin() + pos; column != data.begin() + pos + num; ++column) {
for (auto* item : *column)
delete item;
}
data.erase(data.begin() + pos, data.begin() + pos + num);
for (int i = 0; i < num; ++i) {
delete col_info_list[pos + i];
}
col_info_list.erase(col_info_list.begin() + pos, col_info_list.begin() + pos + num);
return true;
}
Cell_Info Memory_Table_Model::get_span(int xi, int yi) {
int col_num = data.size();
int row_num = data.front().size();
Base_Table_Data* that = data[xi][yi];
int col_span = 1;
int row_span = 1;
int sw = col_info_list[xi]->len;
int sh = row_info_list[yi]->len;
while (true) {
int index = xi + col_span;
if (index >= col_num)
break;
auto cur = data[index][yi];
if (cur->parent != that) {
break;
}
sw += col_info_list[index]->len + col_space;
col_span++;
}
while (true) {
int index = yi + row_span;
if (index >= row_num)
break;
auto cur = data[xi][index];
if (cur->parent != that) {
break;
}
sh += row_info_list[index]->len + row_space;
row_span++;
}
return {col_span, row_span, sw, sh};
}
Find_Ret Memory_Table_Model::find_parent(Base_Table_Data* parent, int xi, int yi) {
int cur_x = xi;
int cur_y = yi;
if (xi != 0) {
while (true) {
auto cur = data[cur_x - 1][yi];
if (cur->parent != parent && cur->parent != nullptr) {
break;
}
cur_x--;
if (cur_x == 0)
break;
}
}
if (yi != 0) {
while (true) {
auto cur = data[xi][cur_y - 1];
if (cur->parent != parent && cur->parent != nullptr) {
break;
}
cur_y--;
if (cur_y == 0)
break;
}
}
// qDebug() << "find_parent: " << data[xi][yi]->content << " " << cur_x << " " << cur_y;
return {cur_x, cur_y};
}
} // namespace Psc