merge: issue/local-files-and-windows-runtime — convencion local_files/
Adopta la convencion local_files/ del framework para separar distribuibles (.exe, dlls, enrichers/, runtime/) de estado del usuario (settings, DBs, proyectos). Con esto + el runtime Python embebido (Windows) ya copiado al Desktop, la app es completamente portable a otra maquina Windows sin WSL ni fn_registry montado.
This commit is contained in:
@@ -1912,9 +1912,11 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (legacy_mode) {
|
if (legacy_mode) {
|
||||||
// Modo legacy: paths sueltos junto al exe (compat con flujo anterior)
|
// Modo legacy: paths sueltos en local_files/ (graph_explorer.db
|
||||||
ge::layout_store_open("graph_explorer.db");
|
// como fallback cuando no se ha cargado un proyecto).
|
||||||
g_layout_db_path = "graph_explorer.db";
|
std::string legacy_db = fn::local_path("graph_explorer.db");
|
||||||
|
ge::layout_store_open(legacy_db.c_str());
|
||||||
|
g_layout_db_path = legacy_db;
|
||||||
if (!g_input_path.empty()) {
|
if (!g_input_path.empty()) {
|
||||||
load_input();
|
load_input();
|
||||||
}
|
}
|
||||||
@@ -1969,8 +1971,10 @@ int main(int argc, char** argv) {
|
|||||||
std::string enrichers_dir = app_dir + "/enrichers";
|
std::string enrichers_dir = app_dir + "/enrichers";
|
||||||
|
|
||||||
// graph_explorer.db es el mismo SQLite usado por layout_store.
|
// graph_explorer.db es el mismo SQLite usado por layout_store.
|
||||||
|
// Default a <local_files>/graph_explorer.db si no hay proyecto.
|
||||||
|
std::string fallback_db = fn::local_path("graph_explorer.db");
|
||||||
const char* app_db = g_layout_db_path.empty()
|
const char* app_db = g_layout_db_path.empty()
|
||||||
? "graph_explorer.db" : g_layout_db_path.c_str();
|
? fallback_db.c_str() : g_layout_db_path.c_str();
|
||||||
|
|
||||||
// Layout storage — guardado/cargado de layouts ImGui en
|
// Layout storage — guardado/cargado de layouts ImGui en
|
||||||
// graph_explorer.db. El menu Layouts del menubar consume estos cb.
|
// graph_explorer.db. El menu Layouts del menubar consume estos cb.
|
||||||
|
|||||||
+17
-7
@@ -1,5 +1,7 @@
|
|||||||
#include "project_manager.h"
|
#include "project_manager.h"
|
||||||
|
|
||||||
|
#include "../../../../cpp/framework/app_base.h"
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -20,6 +22,14 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
namespace ge {
|
namespace ge {
|
||||||
|
|
||||||
|
// Helpers de paths — resuelven contra <exe_dir>/local_files/.
|
||||||
|
const char* projects_root() {
|
||||||
|
return fn::local_path(k_projects_subdir);
|
||||||
|
}
|
||||||
|
const char* settings_path() {
|
||||||
|
return fn::local_path(k_settings_basename);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// DDL embebido (operations.db schema)
|
// DDL embebido (operations.db schema)
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -217,7 +227,7 @@ bool project_validate_slug(const char* name, std::string* error_msg) {
|
|||||||
ProjectPaths project_paths(const char* slug) {
|
ProjectPaths project_paths(const char* slug) {
|
||||||
ProjectPaths p;
|
ProjectPaths p;
|
||||||
if (!slug || !*slug) return p;
|
if (!slug || !*slug) return p;
|
||||||
fs::path root = fs::path(k_projects_dir) / slug;
|
fs::path root = fs::path(projects_root()) / slug;
|
||||||
p.root_dir = root.string();
|
p.root_dir = root.string();
|
||||||
p.operations_db = (root / "operations.db").string();
|
p.operations_db = (root / "operations.db").string();
|
||||||
p.types_yaml = (root / "types.yaml").string();
|
p.types_yaml = (root / "types.yaml").string();
|
||||||
@@ -231,7 +241,7 @@ ProjectPaths project_paths(const char* slug) {
|
|||||||
|
|
||||||
bool projects_root_ensure() {
|
bool projects_root_ensure() {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
fs::create_directories(k_projects_dir, ec);
|
fs::create_directories(projects_root(), ec);
|
||||||
return !ec;
|
return !ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,8 +249,8 @@ bool project_list(std::vector<std::string>* out) {
|
|||||||
if (!out) return false;
|
if (!out) return false;
|
||||||
out->clear();
|
out->clear();
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (!fs::exists(k_projects_dir, ec)) return true;
|
if (!fs::exists(projects_root(), ec)) return true;
|
||||||
for (auto& e : fs::directory_iterator(k_projects_dir, ec)) {
|
for (auto& e : fs::directory_iterator(projects_root(), ec)) {
|
||||||
if (ec) break;
|
if (ec) break;
|
||||||
if (!e.is_directory()) continue;
|
if (!e.is_directory()) continue;
|
||||||
std::string slug = e.path().filename().string();
|
std::string slug = e.path().filename().string();
|
||||||
@@ -346,7 +356,7 @@ bool project_create(const char* slug, std::string* error_msg) {
|
|||||||
|
|
||||||
bool projects_migrate_legacy_layout() {
|
bool projects_migrate_legacy_layout() {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (fs::exists(k_projects_dir, ec)) return true; // ya migrado o creado
|
if (fs::exists(projects_root(), ec)) return true; // ya migrado o creado
|
||||||
|
|
||||||
bool has_operations = fs::exists("operations.db", ec);
|
bool has_operations = fs::exists("operations.db", ec);
|
||||||
bool has_layout = fs::exists("graph_explorer.db", ec);
|
bool has_layout = fs::exists("graph_explorer.db", ec);
|
||||||
@@ -423,7 +433,7 @@ static std::vector<std::string> split_csv(const std::string& s) {
|
|||||||
bool project_settings_load(ProjectSettings* out) {
|
bool project_settings_load(ProjectSettings* out) {
|
||||||
if (!out) return false;
|
if (!out) return false;
|
||||||
*out = {};
|
*out = {};
|
||||||
std::ifstream in(k_settings_file);
|
std::ifstream in(settings_path());
|
||||||
if (!in) return true; // no es error: archivo aun no existe
|
if (!in) return true; // no es error: archivo aun no existe
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(in, line)) {
|
while (std::getline(in, line)) {
|
||||||
@@ -440,7 +450,7 @@ bool project_settings_load(ProjectSettings* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool project_settings_save(const ProjectSettings& s) {
|
bool project_settings_save(const ProjectSettings& s) {
|
||||||
std::ofstream out(k_settings_file);
|
std::ofstream out(settings_path());
|
||||||
if (!out) return false;
|
if (!out) return false;
|
||||||
out << "# graph_explorer.ini — autogenerado, editable\n";
|
out << "# graph_explorer.ini — autogenerado, editable\n";
|
||||||
out << "last_active = " << s.last_active << "\n";
|
out << "last_active = " << s.last_active << "\n";
|
||||||
|
|||||||
+22
-11
@@ -7,23 +7,34 @@
|
|||||||
// contiene sus propios `operations.db`, `types.yaml` y `graph_explorer.db`
|
// contiene sus propios `operations.db`, `types.yaml` y `graph_explorer.db`
|
||||||
// (layouts). El usuario crea proyectos, los nombra y conmuta entre ellos.
|
// (layouts). El usuario crea proyectos, los nombra y conmuta entre ellos.
|
||||||
//
|
//
|
||||||
// Layout en disco:
|
// Layout en disco (issue: convencion local_files):
|
||||||
//
|
//
|
||||||
// <exe_dir>/
|
// <exe_dir>/
|
||||||
// graph_explorer.ini # last_active + recent (gestionado aqui)
|
// graph_explorer.exe
|
||||||
// projects/
|
// enrichers/, runtime/, *.ttf, ... (read-only, distribuibles)
|
||||||
// default/
|
// local_files/ (escribibles, per-PC)
|
||||||
// operations.db # bootstrap con DDL completo
|
// imgui.ini, app_settings.ini (gestionados por fn_framework)
|
||||||
// types.yaml # copia editable; semilla = ./examples/types.yaml o embed
|
// graph_explorer.ini # last_active + recent
|
||||||
// graph_explorer.db # layouts del proyecto
|
// projects/
|
||||||
// caso_X/
|
// default/
|
||||||
// ...
|
// operations.db
|
||||||
|
// types.yaml
|
||||||
|
// graph_explorer.db # layouts del proyecto
|
||||||
|
// caso_X/
|
||||||
|
// ...
|
||||||
|
|
||||||
namespace ge {
|
namespace ge {
|
||||||
|
|
||||||
constexpr const char* k_projects_dir = "projects";
|
// Helpers que resuelven a <exe_dir>/local_files/... via fn::local_path.
|
||||||
|
// Las constantes solo guardan el basename relativo a local_files/.
|
||||||
|
constexpr const char* k_projects_subdir = "projects";
|
||||||
constexpr const char* k_default_project = "default";
|
constexpr const char* k_default_project = "default";
|
||||||
constexpr const char* k_settings_file = "graph_explorer.ini";
|
constexpr const char* k_settings_basename = "graph_explorer.ini";
|
||||||
|
|
||||||
|
// Devuelven paths absolutos resueltos contra local_files/ (creando la
|
||||||
|
// carpeta si no existe). Sustituyen el uso directo de los constexpr.
|
||||||
|
const char* projects_root(); // <exe>/local_files/projects
|
||||||
|
const char* settings_path(); // <exe>/local_files/graph_explorer.ini
|
||||||
|
|
||||||
struct ProjectPaths {
|
struct ProjectPaths {
|
||||||
std::string root_dir; // <exe>/projects/<slug>/
|
std::string root_dir; // <exe>/projects/<slug>/
|
||||||
|
|||||||
Reference in New Issue
Block a user