feat(0035d): doble click en Group abre tableview filtrado por group_id
- entity_ops: EntityRowSnapshot.group_id + SQL con COALESCE(group_id,'') + deteccion via PRAGMA para BDs viejas sin la columna. - views.h: TableRow.group_id + AppState.table_filter_group_id / table_filter_group_name (RAM-only). - main.cpp: dispatch en want_open_note — si type_ref == "Group", setea filtro de grupo + abre panel Table en vez de Note. Reset de search buf y col_filters al entrar al drill-in para que el usuario vea todo el contenido del grupo. - views.cpp: build_visible compone group_id con search/tabs/col_filters (AND). types_present se reduce a tipos presentes en el grupo cuando hay drill-in activo. Header pintado en amarillo con TI_FOLDER + contador + boton "Clear group filter". Al cerrarse el panel se limpia el filtro automaticamente. Tests: pytest 35 passed (WSL) / 24 passed + 11 skipped (Windows). Refs: issues/0035d-tableview-drill-in.md
This commit is contained in:
@@ -729,6 +729,7 @@ static bool load_input(bool first_load) {
|
||||
tr.type_ref = std::move(s.type_ref);
|
||||
tr.status = std::move(s.status);
|
||||
tr.updated_at = std::move(s.updated_at);
|
||||
tr.group_id = std::move(s.group_id);
|
||||
g_app.table_rows.push_back(std::move(tr));
|
||||
}
|
||||
ge::views_table_refresh_indices(g_app);
|
||||
@@ -1558,6 +1559,7 @@ static void render() {
|
||||
tr.type_ref = std::move(s.type_ref);
|
||||
tr.status = std::move(s.status);
|
||||
tr.updated_at = std::move(s.updated_at);
|
||||
tr.group_id = std::move(s.group_id);
|
||||
g_app.table_rows.push_back(std::move(tr));
|
||||
}
|
||||
ge::views_table_refresh_indices(g_app);
|
||||
@@ -1855,21 +1857,40 @@ static void render() {
|
||||
}
|
||||
|
||||
// Note editor — abrir / guardar.
|
||||
// Excepcion (issue 0035d): si el nodo es un Group, en lugar de abrir
|
||||
// Note se abre el panel Table con filtro por group_id.
|
||||
if (g_app.want_open_note && g_app.open_note_target >= 0
|
||||
&& g_app.open_note_target < g_graph.node_count) {
|
||||
int n = g_app.open_note_target;
|
||||
const char* sql_id = ge::entity_index_lookup(g_idx, g_graph.nodes[n].user_data);
|
||||
if (sql_id) {
|
||||
|
||||
// Detectar si el nodo es de tipo Group.
|
||||
bool is_group = false;
|
||||
uint16_t tid = g_graph.nodes[n].type_id;
|
||||
const char* type_name = (tid < (uint16_t)g_graph.type_count
|
||||
&& g_graph.types[tid].name)
|
||||
? g_graph.types[tid].name : "";
|
||||
if (type_name && std::strcmp(type_name, "Group") == 0) is_group = true;
|
||||
|
||||
if (is_group && sql_id) {
|
||||
// Drill-in: abrir tableview filtrada por group_id = sql_id.
|
||||
g_app.table_filter_group_id = sql_id;
|
||||
const char* lbl = graph::graph_label(&g_graph, g_graph.nodes[n].label_idx);
|
||||
g_app.table_filter_group_name = lbl ? lbl : sql_id;
|
||||
// Reset filtros que pueden ocultar las filas del grupo.
|
||||
g_app.table_search_buf[0] = 0;
|
||||
g_app.table_col_filters.clear();
|
||||
g_app.table_show_all = true;
|
||||
g_app.panel_table = true;
|
||||
ImGui::SetWindowFocus("Table");
|
||||
} else if (sql_id) {
|
||||
std::string md;
|
||||
ge::entity_get_notes(g_app.input_db_path.c_str(), sql_id, &md);
|
||||
g_app.note_node = n;
|
||||
g_app.note_entity_id = sql_id;
|
||||
const char* lbl = graph::graph_label(&g_graph, g_graph.nodes[n].label_idx);
|
||||
g_app.note_entity_label = lbl ? lbl : "";
|
||||
uint16_t tid = g_graph.nodes[n].type_id;
|
||||
g_app.note_entity_type = (tid < (uint16_t)g_graph.type_count
|
||||
&& g_graph.types[tid].name)
|
||||
? g_graph.types[tid].name : "";
|
||||
g_app.note_entity_type = type_name;
|
||||
// Asegura buffer >= max(64KB, contenido + holgura).
|
||||
size_t need = md.size() + 4096;
|
||||
if (need < 65536) need = 65536;
|
||||
|
||||
Reference in New Issue
Block a user