Skip to content

Commit

Permalink
disable editing for repeated cells
Browse files Browse the repository at this point in the history
  • Loading branch information
andiwand committed Dec 10, 2023
1 parent 23e552d commit c4255fc
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 66 deletions.
4 changes: 4 additions & 0 deletions src/odr/document_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}; }
Expand Down
2 changes: 2 additions & 0 deletions src/odr/document_element.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/odr/internal/html/document_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void html::translate_text(const Element element, std::ostream &out,

out << "<x-s";
out << optional_style_attribute(translate_text_style(text.style()));
if (config.editable) {
if (config.editable && element.is_editable()) {
out << " contenteditable=\"true\"";
out << " data-odr-path=\"" << DocumentPath::extract(element).to_string()
<< "\"";
Expand Down
127 changes: 75 additions & 52 deletions src/odr/internal/odf/odf_spreadsheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,57 @@

namespace odr::internal::odf {

void SheetIndex::init_column(std::uint32_t column, std::uint32_t repeated,
pugi::xml_node element) {
columns[column + repeated] = element;
}

void SheetIndex::init_row(std::uint32_t row, std::uint32_t repeated,
pugi::xml_node element) {
rows[row + repeated].row = element;
}

void SheetIndex::init_cell(std::uint32_t column, std::uint32_t row,
std::uint32_t columns_repeated,
std::uint32_t rows_repeated,
pugi::xml_node element) {
rows[row + rows_repeated].cells[column + columns_repeated] = element;
}

pugi::xml_node SheetIndex::column(std::uint32_t column) const {
if (auto it = util::map::lookup_greater_than(columns, column);
it != std::end(columns)) {
return it->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;
Expand Down Expand Up @@ -46,17 +93,22 @@ 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 {
return m_node.attribute("table:name").value();
}

TableDimensions Sheet::dimensions(const abstract::Document *) const {
return m_dimensions;
return m_index.dimensions;
}

TableDimensions
Expand Down Expand Up @@ -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 *,
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -275,6 +297,7 @@ odf::parse_element_tree<odf::Sheet>(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);
Expand All @@ -291,7 +314,7 @@ odf::parse_element_tree<odf::Sheet>(Document &document, pugi::xml_node node) {
column_repeat < columns_repeated; ++column_repeat) {
auto [cell, _] = parse_element_tree<SheetCell>(
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);
}
Expand Down
38 changes: 25 additions & 13 deletions src/odr/internal/odf/odf_spreadsheet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ class SpreadsheetRoot final : public Root {
using Root::Root;
};

struct SheetIndex final {
struct Row {
pugi::xml_node row;
std::map<std::uint32_t, pugi::xml_node> cells;
};

TableDimensions dimensions;

std::map<std::uint32_t, pugi::xml_node> columns;
std::map<std::uint32_t, Row> 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;
Expand Down Expand Up @@ -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<std::uint32_t, pugi::xml_node> cells;
};
SheetIndex m_index;

TableDimensions m_dimensions;

std::map<std::uint32_t, pugi::xml_node> m_columns;
std::map<std::uint32_t, Row> m_rows;
std::unordered_map<common::TablePosition, SheetCell *> m_cells;

Element *m_first_shape{nullptr};
};

Expand Down

0 comments on commit c4255fc

Please sign in to comment.