refactor(0036a): rename Table-expanded -> NodeGroups (paperwork)

Rename masivo sin cambio de comportamiento. Habilita 0036b-f que ya
asumen la nueva convencion.

Archivos:
- tableview.{cpp,h} -> node_groups.{cpp,h} (git mv para preservar history)
- CMakeLists.txt: tableview.cpp -> node_groups.cpp

Tipos:
- TableWindowState  -> NodeGroupsWindowState  (views.h)
- TableMetadata     -> NodeGroupsMeta         (node_groups.h)
- TablePageRow      -> NodeGroupsRow          (node_groups.h)

Campos AppState:
- table_windows         -> node_groups_windows
- table_node_counts     -> node_groups_counts
- toggle_expanded_id    -> toggle_nodegroups_id
- want_toggle_expanded  -> want_toggle_nodegroups

Funciones (window por contenedor — NO el panel generico Table):
- tableview_create / count / page / smoke_test / resolve_path /
  refresh_counts / list_columns / get_metadata / set_expanded /
  set_columns / promote_row / demote_row / ingest_file
  -> prefijo node_groups_*
- views_table_window         -> views_node_groups_window
- views_table_windows_sync   -> views_node_groups_windows_sync
- views_table_overlay        -> views_node_groups_overlay

Strings de UI:
- "Expand table" / "Collapse table" -> "Open NodeGroups" / "Close NodeGroups"
- Window title "<icon> <name>" -> "<icon> NodeGroups: <name>"
- Tooltip "(no expanded tables)" -> "(no open NodeGroups)"
- Logs [tableview_*] -> [node_groups_*]

Preservados intencionalmente (no son cambio de identificadores C++):
- CLI flag --test-tableview (cambiarlo seria cambio de behavior publico)
- Valor 'tableview' en columna entities.source (cambiarlo afectaria
  datos persistidos en BD)

NO tocado:
- Panel generico Table (views_table, panel_table, table_rows,
  table_show_all, table_search_buf, table_filter_*, table_col_filters,
  table_active_tab, TableRow, table_filter_group_*, etc.)
- issues/completed/* (historia)

Verificacion:
- Build C++ Linux + Windows: green sin warnings nuevos.
- pytest WSL: 89 passed.
- pytest Windows: 78 passed + 11 skipped.
- git grep audit: solo residuos en issues/ (historia) + CLI flag y
  source DB value preservados.

Refs: issues/0036a-rename-nodegroups.md
This commit is contained in:
2026-05-04 00:43:01 +02:00
parent 441a697abf
commit 810b564127
7 changed files with 163 additions and 161 deletions
+24 -24
View File
@@ -306,15 +306,15 @@ void views_toolbar(AppState& app) {
{
char btn[64];
std::snprintf(btn, sizeof(btn), TI_TABLE " Tables (%zu)",
app.table_windows.size());
app.node_groups_windows.size());
if (button(btn, ButtonVariant::Subtle)) {
ImGui::OpenPopup("##tables_menu");
}
if (ImGui::BeginPopup("##tables_menu")) {
if (app.table_windows.empty()) {
ImGui::TextDisabled("(no expanded tables)");
if (app.node_groups_windows.empty()) {
ImGui::TextDisabled("(no open NodeGroups)");
} else {
for (auto& kv : app.table_windows) {
for (auto& kv : app.node_groups_windows) {
bool checked = kv.second.open;
char lbl[160];
std::snprintf(lbl, sizeof(lbl), "%s (%lld rows)",
@@ -326,7 +326,7 @@ void views_toolbar(AppState& app) {
}
ImGui::Separator();
if (ImGui::MenuItem(TI_X " Collapse all")) {
for (auto& kv : app.table_windows) kv.second.open = false;
for (auto& kv : app.node_groups_windows) kv.second.open = false;
}
}
ImGui::EndPopup();
@@ -1873,12 +1873,12 @@ void views_table(AppState& app) {
// Table node UI fase 2 (issue 0011) — ventana expandida + import
// ----------------------------------------------------------------------------
void views_table_windows_sync(AppState& app, const char* ops_db) {
void views_node_groups_windows_sync(AppState& app, const char* ops_db) {
if (!app.graph || !ops_db) return;
GraphData& g = *app.graph;
// Construir set de Tables expandidas con su metadata fresca.
std::unordered_map<std::string, TableMetadata> live;
std::unordered_map<std::string, NodeGroupsMeta> live;
for (int i = 0; i < g.node_count; ++i) {
const GraphNode& n = g.nodes[i];
if (n.type_id >= (uint16_t)g.type_count) continue;
@@ -1906,8 +1906,8 @@ void views_table_windows_sync(AppState& app, const char* ops_db) {
const unsigned char* p = sqlite3_column_text(st, 0);
if (!p) continue;
std::string id = (const char*)p;
TableMetadata meta;
if (tableview_get_metadata(ops_db, id.c_str(), &meta)) {
NodeGroupsMeta meta;
if (node_groups_get_metadata(ops_db, id.c_str(), &meta)) {
live.emplace(id, std::move(meta));
}
}
@@ -1915,8 +1915,8 @@ void views_table_windows_sync(AppState& app, const char* ops_db) {
sqlite3_close(db);
// Quitar las que ya no estan expanded.
for (auto it = app.table_windows.begin(); it != app.table_windows.end(); ) {
if (live.find(it->first) == live.end()) it = app.table_windows.erase(it);
for (auto it = app.node_groups_windows.begin(); it != app.node_groups_windows.end(); ) {
if (live.find(it->first) == live.end()) it = app.node_groups_windows.erase(it);
else ++it;
}
// Anadir las nuevas o refrescar metadata. Tras cualquier sync forzamos
@@ -1925,7 +1925,7 @@ void views_table_windows_sync(AppState& app, const char* ops_db) {
// promote/demote/import — donde el flag promoted de cada fila puede
// haber cambiado).
for (auto& kv : live) {
auto& w = app.table_windows[kv.first];
auto& w = app.node_groups_windows[kv.first];
bool was_present = !w.meta.entity_id.empty();
w.meta = std::move(kv.second);
w.open = true;
@@ -1938,18 +1938,18 @@ void views_table_windows_sync(AppState& app, const char* ops_db) {
}
}
void views_table_window(AppState& app) {
if (app.table_windows.empty()) return;
void views_node_groups_window(AppState& app) {
if (app.node_groups_windows.empty()) return;
GraphData* g = app.graph;
GraphViewportState* vp = app.viewport;
for (auto& kv : app.table_windows) {
TableMetadata& m = kv.second.meta;
AppState::TableWindowState& w = kv.second;
for (auto& kv : app.node_groups_windows) {
NodeGroupsMeta& m = kv.second.meta;
AppState::NodeGroupsWindowState& w = kv.second;
char title[160];
std::snprintf(title, sizeof(title), TI_TABLE " %s##te_%s",
m.name.empty() ? "Table" : m.name.c_str(),
std::snprintf(title, sizeof(title), TI_TABLE " NodeGroups: %s##te_%s",
m.name.empty() ? "(unnamed)" : m.name.c_str(),
m.entity_id.c_str());
ImGui::SetNextWindowSize(ImVec2(640, 460), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, &w.open)) { ImGui::End(); continue; }
@@ -1987,7 +1987,7 @@ void views_table_window(AppState& app) {
// avanzamos offset.
const int64_t page_size = 200;
for (int64_t i = 0; i < (int64_t)w.page.size(); ++i) {
const TablePageRow& row = w.page[i];
const NodeGroupsRow& row = w.page[i];
ImGui::TableNextRow();
ImGui::PushID((int)(w.offset + i));
@@ -2080,7 +2080,7 @@ void views_table_window(AppState& app) {
}
// Cerrar la ventana = expanded=false. Lo procesa main.cpp leyendo
// table_windows y comparando `open`.
// node_groups_windows y comparando `open`.
}
bool views_import_dataset_modal(AppState& app) {
@@ -2132,7 +2132,7 @@ bool views_import_dataset_modal(AppState& app) {
// Table node overlay (issue 0010)
// ----------------------------------------------------------------------------
void views_table_overlay(AppState& app) {
void views_node_groups_overlay(AppState& app) {
if (!app.graph || !app.viewport) return;
GraphData& g = *app.graph;
if (g.type_count == 0) return;
@@ -2162,8 +2162,8 @@ void views_table_overlay(AppState& app) {
if (vy < wmin.y - 100 || vy > wmax.y + 100) continue;
int64_t count = -1;
auto it = app.table_node_counts.find(n.user_data);
if (it != app.table_node_counts.end()) count = it->second;
auto it = app.node_groups_counts.find(n.user_data);
if (it != app.node_groups_counts.end()) count = it->second;
if (count < 0) continue;
char buf[64];