From c4255fc0eb3455d08f7012cf3183994223b4d539 Mon Sep 17 00:00:00 2001 From: andiwand Date: Sun, 10 Dec 2023 20:22:25 +0100 Subject: [PATCH] disable editing for repeated cells --- src/odr/document_element.cpp | 4 + src/odr/document_element.hpp | 2 + src/odr/internal/html/document_element.cpp | 2 +- src/odr/internal/odf/odf_spreadsheet.cpp | 127 ++++++++++++--------- src/odr/internal/odf/odf_spreadsheet.hpp | 38 +++--- 5 files changed, 107 insertions(+), 66 deletions(-) diff --git a/src/odr/document_element.cpp b/src/odr/document_element.cpp index e6033d07..9dcd2ec2 100644 --- a/src/odr/document_element.cpp +++ b/src/odr/document_element.cpp @@ -51,6 +51,10 @@ Element Element::next_sibling() const { : Element(); } +bool Element::is_editable() const { + return exists_() ? m_element->is_editable(m_document) : false; +} + TextRoot Element::text_root() const { return {m_document, m_element}; } Slide Element::slide() const { return {m_document, m_element}; } diff --git a/src/odr/document_element.hpp b/src/odr/document_element.hpp index a0147b85..f2892698 100644 --- a/src/odr/document_element.hpp +++ b/src/odr/document_element.hpp @@ -146,6 +146,8 @@ class Element { [[nodiscard]] Element previous_sibling() const; [[nodiscard]] Element next_sibling() const; + [[nodiscard]] bool is_editable() const; + [[nodiscard]] ElementRange children() const; [[nodiscard]] TextRoot text_root() const; diff --git a/src/odr/internal/html/document_element.cpp b/src/odr/internal/html/document_element.cpp index a5af7718..4e7e428c 100644 --- a/src/odr/internal/html/document_element.cpp +++ b/src/odr/internal/html/document_element.cpp @@ -227,7 +227,7 @@ void html::translate_text(const Element element, std::ostream &out, out << "second; + } + return {}; +} + +pugi::xml_node SheetIndex::row(std::uint32_t row) const { + if (auto it = util::map::lookup_greater_than(rows, row); + it != std::end(rows)) { + return it->second.row; + } + return {}; +} + +pugi::xml_node SheetIndex::cell(std::uint32_t column, std::uint32_t row) const { + if (auto row_it = util::map::lookup_greater_than(rows, row); + row_it != std::end(rows)) { + const auto &cells = row_it->second.cells; + if (auto cell_it = util::map::lookup_greater_than(cells, column); + cell_it != std::end(cells)) { + return cell_it->second; + } + } + return {}; +} + class SheetCell final : public Element, public abstract::SheetCell { public: - SheetCell(pugi::xml_node node, std::uint32_t column, std::uint32_t row) - : Element(node), m_column{column}, m_row{row} {} + SheetCell(pugi::xml_node node, std::uint32_t column, std::uint32_t row, + bool is_repeated) + : Element(node), m_column{column}, m_row{row}, m_is_repeated{ + is_repeated} {} [[nodiscard]] bool is_covered(const abstract::Document *) const final { return std::strcmp(m_node.name(), "table:covered-table-cell") == 0; @@ -46,9 +93,14 @@ class SheetCell final : public Element, public abstract::SheetCell { return intermediate_style(document).table_cell_style; } + bool is_editable(const abstract::Document *) const final { + return !m_is_repeated; + } + private: - std::uint32_t m_column; - std::uint32_t m_row; + std::uint32_t m_column{}; + std::uint32_t m_row{}; + bool m_is_repeated{}; }; std::string Sheet::name(const abstract::Document *) const { @@ -56,7 +108,7 @@ std::string Sheet::name(const abstract::Document *) const { } TableDimensions Sheet::dimensions(const abstract::Document *) const { - return m_dimensions; + return m_index.dimensions; } TableDimensions @@ -92,65 +144,37 @@ Sheet::content(const abstract::Document *, return result; } -pugi::xml_node Sheet::column_(std::uint32_t column) const { - if (auto it = util::map::lookup_greater_than(m_columns, column); - it != std::end(m_columns)) { - return it->second; - } - return {}; -} - -pugi::xml_node Sheet::row_(std::uint32_t row) const { - if (auto it = util::map::lookup_greater_than(m_rows, row); - it != std::end(m_rows)) { - return it->second.row; - } - return {}; -} - -pugi::xml_node Sheet::cell_(std::uint32_t column, std::uint32_t row) const { - if (auto row_it = util::map::lookup_greater_than(m_rows, row); - row_it != std::end(m_rows)) { - const auto &cells = row_it->second.cells; - if (auto cell_it = util::map::lookup_greater_than(cells, column); - cell_it != std::end(cells)) { - return cell_it->second; - } - } - return {}; -} - common::ResolvedStyle Sheet::cell_style_(const abstract::Document *document, std::uint32_t column, std::uint32_t row) const { const char *style_name = nullptr; - auto cell_node = cell_(column, row); + auto cell_node = m_index.cell(column, row); if (auto attr = cell_node.attribute("table:style-name")) { style_name = attr.value(); } if (style_name == nullptr) { - auto row_node = row_(row); + auto row_node = m_index.row(row); if (auto attr = row_node.attribute("table:default-cell-style-name")) { style_name = attr.value(); } } if (style_name == nullptr) { - auto column_node = column_(column); + auto column_node = m_index.column(column); if (auto attr = column_node.attribute("table:default-cell-style-name")) { style_name = attr.value(); } } - if (style_name == nullptr) { - return common::ResolvedStyle(); - } - auto style = style_(document)->style(style_name); - if (style == nullptr) { - return common::ResolvedStyle(); + if (style_name != nullptr) { + auto style = style_(document)->style(style_name); + if (style != nullptr) { + return style->resolved(); + } } - return style->resolved(); + + return common::ResolvedStyle(); } abstract::SheetCell *Sheet::cell(const abstract::Document *, @@ -173,8 +197,7 @@ TableStyle Sheet::style(const abstract::Document *document) const { TableColumnStyle Sheet::column_style(const abstract::Document *document, std::uint32_t column) const { - auto column_node = column_(column); - if (column_node) { + if (auto column_node = m_index.column(column); column_node) { if (auto attr = column_node.attribute("table:style-name")) { auto style = style_(document)->style(attr.value()); if (style != nullptr) { @@ -187,8 +210,7 @@ TableColumnStyle Sheet::column_style(const abstract::Document *document, TableRowStyle Sheet::row_style(const abstract::Document *document, std::uint32_t row) const { - auto column_node = row_(row); - if (column_node) { + if (auto column_node = m_index.row(row); column_node) { if (auto attr = column_node.attribute("table:style-name")) { auto style = style_(document)->style(attr.value()); if (style != nullptr) { @@ -207,18 +229,18 @@ TableCellStyle Sheet::cell_style(const abstract::Document *document, void Sheet::init_column_(std::uint32_t column, std::uint32_t repeated, pugi::xml_node element) { - m_columns[column + repeated] = element; + m_index.init_column(column, repeated, element); } void Sheet::init_row_(std::uint32_t row, std::uint32_t repeated, pugi::xml_node element) { - m_rows[row + repeated].row = element; + m_index.init_row(row, repeated, element); } void Sheet::init_cell_(std::uint32_t column, std::uint32_t row, std::uint32_t columns_repeated, std::uint32_t rows_repeated, pugi::xml_node element) { - m_rows[row + rows_repeated].cells[column + columns_repeated] = element; + m_index.init_cell(column, row, columns_repeated, rows_repeated, element); } void Sheet::init_cell_element_(std::uint32_t column, std::uint32_t row, @@ -228,7 +250,7 @@ void Sheet::init_cell_element_(std::uint32_t column, std::uint32_t row, } void Sheet::init_dimensions_(TableDimensions dimensions) { - m_dimensions = dimensions; + m_index.dimensions = dimensions; } } // namespace odr::internal::odf @@ -275,6 +297,7 @@ odf::parse_element_tree(Document &document, pugi::xml_node node) { cell_node.attribute("table:number-columns-spanned").as_uint(1); const auto rowspan = cell_node.attribute("table:number-rows-spanned").as_uint(1); + const bool is_repeated = (columns_repeated > 1) || (rows_repeated > 1); sheet.init_cell_(cursor.column(), cursor.row(), columns_repeated, rows_repeated, cell_node); @@ -291,7 +314,7 @@ odf::parse_element_tree(Document &document, pugi::xml_node node) { column_repeat < columns_repeated; ++column_repeat) { auto [cell, _] = parse_element_tree( document, cell_node, cursor.column() + column_repeat, - cursor.row() + row_repeat); + cursor.row() + row_repeat, is_repeated); sheet.init_cell_element_(cursor.column() + column_repeat, cursor.row() + row_repeat, cell); } diff --git a/src/odr/internal/odf/odf_spreadsheet.hpp b/src/odr/internal/odf/odf_spreadsheet.hpp index 81f3bc6c..24391166 100644 --- a/src/odr/internal/odf/odf_spreadsheet.hpp +++ b/src/odr/internal/odf/odf_spreadsheet.hpp @@ -25,6 +25,30 @@ class SpreadsheetRoot final : public Root { using Root::Root; }; +struct SheetIndex final { + struct Row { + pugi::xml_node row; + std::map cells; + }; + + TableDimensions dimensions; + + std::map columns; + std::map rows; + + void init_column(std::uint32_t column, std::uint32_t repeated, + pugi::xml_node element); + void init_row(std::uint32_t row, std::uint32_t repeated, + pugi::xml_node element); + void init_cell(std::uint32_t column, std::uint32_t row, + std::uint32_t columns_repeated, std::uint32_t rows_repeated, + pugi::xml_node element); + + pugi::xml_node column(std::uint32_t) const; + pugi::xml_node row(std::uint32_t) const; + pugi::xml_node cell(std::uint32_t column, std::uint32_t row) const; +}; + class Sheet final : public Element, public abstract::Sheet { public: using Element::Element; @@ -64,26 +88,14 @@ class Sheet final : public Element, public abstract::Sheet { SheetCell *element); void init_dimensions_(TableDimensions dimensions); - pugi::xml_node column_(std::uint32_t) const; - pugi::xml_node row_(std::uint32_t) const; - pugi::xml_node cell_(std::uint32_t column, std::uint32_t row) const; - common::ResolvedStyle cell_style_(const abstract::Document *, std::uint32_t column, std::uint32_t row) const; private: - struct Row { - pugi::xml_node row; - std::map cells; - }; + SheetIndex m_index; - TableDimensions m_dimensions; - - std::map m_columns; - std::map m_rows; std::unordered_map m_cells; - Element *m_first_shape{nullptr}; };