Files
essim/src/core/imports/ods_writer.hpp
François 63ca17d048 build: split core/ from frontends/; prepare for multiple GUI/TUI targets
Reorganise the tree into business vs frontend as separate directories:
  src/core/{domain,imports,app}   (was system/, imports/, app/)
  src/frontends/tui/              (was tui/ + main.cpp)
  tests/tui/                      (the FTXUI-coupled helper test)
All cross-dir #include paths rewritten; same-dir includes untouched.

CMake: essim_core is the frontend-agnostic business library — links libzip,
pugixml and bsdl, NO GUI toolkit. Each frontend is a self-contained
src/frontends/<name>/ (own CMakeLists, toolkit, main.cpp) that links
essim_core, selected with -DESSIM_FRONTEND=<name> (default tui; 'none' = core +
tests only, no toolkit fetched). FTXUI moved into the tui frontend. Tests are
split: essim_tests links essim_core (no FTXUI), essim_tui_tests links essim_tui.

Verified: default tui build green (ctest 2/2); ESSIM_FRONTEND=none builds the
core + tests with FTXUI never fetched and no `essim` binary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 19:33:06 +02:00

63 lines
2.0 KiB
C++

#ifndef _IMPORTS_ODS_WRITER_HPP_
#define _IMPORTS_ODS_WRITER_HPP_
#include <string>
#include <vector>
// Minimal OpenDocument Spreadsheet (.ods) writer. Backed by libzip +
// pugixml (already in the build for the ODS *importer*). Produces
// multi-sheet workbooks; each sheet is a 2-D grid of string cells.
//
// Usage:
// OdsWriter w;
// auto *s1 = w.add_sheet("connection A");
// s1->set(0, 0, "header1");
// s1->set(0, 1, "header2");
// s1->set(1, 0, "value");
// std::string err;
// bool ok = w.save("out.ods", err);
//
// Limitations (intentional, the format is huge):
// - string cells only (no numbers / dates / formulas)
// - no styles, no merged cells, no formatting
// - a single empty row is emitted when a row has at least one set cell;
// trailing empty rows are skipped.
class OdsSheet {
public:
explicit OdsSheet(std::string name) : name_(std::move(name)) {}
void set(int row, int col, std::string value);
// Index of the row that holds the column headers — gets the bold/grey
// style, anchors the freeze, and is the first row of the auto-filter
// range. Rows above it are rendered un-styled (a place for free-form
// metadata such as the connection name). Default 0 = first row is
// the header (no meta block).
void set_header_row(int r) { header_row_ = r; }
int header_row() const { return header_row_; }
const std::string &name() const { return name_; }
int rows() const { return (int)cells_.size(); }
int cols() const;
const std::string &cell(int row, int col) const;
private:
std::string name_;
int header_row_ = 0;
// Row-major sparse storage: cells_[r][c] = value. Rows/cols are grown
// lazily on set().
std::vector<std::vector<std::string>> cells_;
};
class OdsWriter {
public:
OdsSheet *add_sheet(const std::string &name);
bool save(const std::string &path, std::string &error) const;
private:
std::vector<OdsSheet> sheets_;
};
#endif // _IMPORTS_ODS_WRITER_HPP_