From 9ef51ca9815bb09ff0887a1c8311a399028a81db Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 27 Apr 2024 19:56:39 +0200 Subject: [PATCH] RdbCell#layout_name and RdbItem#comment with tests and GSI binding --- src/rdb/rdb/gsiDeclRdb.cc | 33 +++++++++++++++--- src/rdb/rdb/rdb.cc | 22 ++++++++---- src/rdb/rdb/rdb.h | 62 ++++++++++++++++++++++++++++++---- src/rdb/rdb/rdbFile.cc | 4 ++- src/rdb/unit_tests/rdbTests.cc | 7 ++-- testdata/ruby/rdbTest.rb | 22 ++++++++---- 6 files changed, 121 insertions(+), 29 deletions(-) diff --git a/src/rdb/rdb/gsiDeclRdb.cc b/src/rdb/rdb/gsiDeclRdb.cc index e47297b92..36e134da3 100644 --- a/src/rdb/rdb/gsiDeclRdb.cc +++ b/src/rdb/rdb/gsiDeclRdb.cc @@ -265,17 +265,25 @@ Class decl_RdbCell ("rdb", "RdbCell", "The cell name is an string that identifies the category in the database. " "Additionally, a cell may carry a variant identifier which is a string that uniquely identifies a cell " "in the context of its variants. The \"qualified name\" contains both the cell name and the variant name. " - "Cell names are also used to identify report database cell's with layout cells. " + "Cell names are also used to identify report database cells with layout cells. For variants, the layout cell name " + "can be specified explicitly with the \\layout_name attribute (see \\RdbDatabase#create_cell). The latter is available " + "since version 0.29.1.\n" "@return The cell name\n" ) + gsi::method ("variant", &rdb::Cell::variant, "@brief Gets the cell variant name\n" "A variant name additionally identifies the cell when multiple cells with the same name are present. " - "A variant name is either assigned automatically or set when creating a cell. " + "A variant name is either assigned automatically or set when creating a cell.\n" "@return The cell variant name\n" ) + - gsi::method ("qname", &rdb::Cell::qname, - "@brief Gets the cell's qualified name\n" + gsi::method ("layout_name", &rdb::Cell::layout_name, + "@brief Gets the name of the layout cell\n" + "For variants, this string is the name of the actual layout cell. If empty, the cell is assume to be called 'name'.\n" + "@return The layout cell name\n" + "This read-only attribute has been added in version 0.29.1.\n" + ) + + gsi::method ("qname", &rdb::Cell::qname, + "@brief Gets the qualified name of the cell\n" "The qualified name is a combination of the cell name and optionally the variant name. " "It is used to identify the cell by name in a unique way.\n" "@return The qualified name\n" @@ -932,6 +940,19 @@ Class decl_RdbItem ("rdb", "RdbItem", "See \\image_str how to obtain the image.\n\n" "This method has been introduced in version 0.28.\n" ) + + gsi::method ("comment", &rdb::Item::comment, + "@brief Gets the common associated with this item as a string\n" + "@return The comment string\n" + "The comment string is an arbitrary string added by the user to the item.\n" + "\n" + "This attribute has been added in version 0.29.1.\n" + ) + + gsi::method ("comment=", &rdb::Item::set_comment, gsi::arg ("comment"), + "@brief Sets the common associated with this item as a string\n" + "See \\comment for a description of that attribute.\n" + "\n" + "This attribute has been added in version 0.29.1.\n" + ) + gsi::method ("image_str", &rdb::Item::image_str, "@brief Gets the image associated with this item as a string\n" "@return A base64-encoded image file (in PNG format)\n" @@ -1348,10 +1369,12 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "@brief Creates a new cell\n" "@param name The name of the cell\n" ) + - gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"), gsi::arg ("variant"), + gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &, const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"), gsi::arg ("variant"), gsi::arg ("layout_name", std::string ()), "@brief Creates a new cell, potentially as a variant for a cell with the same name\n" "@param name The name of the cell\n" "@param variant The variant name of the cell\n" + "@param layout_name For variants, this is the name of the layout cell. If empty, 'name' is used for the layout cell name.\n" + "The 'layout_name' argument has been added in version 0.29.1.\n" ) + gsi::method ("variants", &rdb::Database::variants, gsi::arg ("name"), "@brief Gets the variants for a given cell name\n" diff --git a/src/rdb/rdb/rdb.cc b/src/rdb/rdb/rdb.cc index 807d0c668..a2e352144 100644 --- a/src/rdb/rdb/rdb.cc +++ b/src/rdb/rdb/rdb.cc @@ -516,7 +516,7 @@ Cells::import_cell (const Cell &c) { Cell *cell; if (mp_database) { - cell = mp_database->create_cell (c.name (), c.variant ()); + cell = mp_database->create_cell (c.name (), c.variant (), c.layout_name ()); } else { cell = new Cell (0, c.name ()); add_cell (cell); @@ -548,8 +548,8 @@ Cell::Cell (id_type id, const std::string &name) // .. nothing yet .. } -Cell::Cell (id_type id, const std::string &name, const std::string &variant) - : m_id (id), m_name (name), m_variant (variant), m_num_items (0), m_num_items_visited (0), mp_database (0) +Cell::Cell (id_type id, const std::string &name, const std::string &variant, const std::string &layout_name = std::string ()) + : m_id (id), m_name (name), m_variant (variant), m_layout_name (layout_name), m_num_items (0), m_num_items_visited (0), mp_database (0) { // .. nothing yet .. } @@ -939,6 +939,7 @@ Item &Item::operator= (const Item &d) m_category_id = d.m_category_id; m_visited = d.m_visited; m_multiplicity = d.m_multiplicity; + m_comment = d.m_comment; m_tag_ids = d.m_tag_ids; m_image_str = d.m_image_str; } @@ -1321,7 +1322,7 @@ Database::category_by_id_non_const (id_type id) } Cell * -Database::create_cell (const std::string &name, const std::string &variant) +Database::create_cell (const std::string &name, const std::string &variant, const std::string &layout_name) { set_modified (); @@ -1358,13 +1359,13 @@ Database::create_cell (const std::string &name, const std::string &variant) } } - new_cell = new Cell (++m_next_id, name, tl::to_string (variant_index + 1)); + new_cell = new Cell (++m_next_id, name, tl::to_string (variant_index + 1), layout_name); variant->second.push_back (new_cell->id ()); } else { - new_cell = new Cell (++m_next_id, name); + new_cell = new Cell (++m_next_id, name, std::string (), layout_name); } @@ -1374,7 +1375,7 @@ Database::create_cell (const std::string &name, const std::string &variant) } else { - new_cell = new Cell (++m_next_id, name, variant); + new_cell = new Cell (++m_next_id, name, variant, layout_name); m_cells.add_cell (new_cell); m_cells_by_id.insert (std::make_pair (new_cell->id (), new_cell)); m_cells_by_qname.insert (std::make_pair (new_cell->qname (), new_cell)); @@ -1468,6 +1469,13 @@ Database::remove_item_tag (const Item *item, id_type tag) const_cast (item)->remove_tag (tag); } +void +Database::set_item_comment (const Item *item, const std::string &comment) +{ + set_modified (); + const_cast (item)->set_comment (comment); +} + #if defined(HAVE_QT) void Database::set_item_image (const Item *item, const QImage &image) diff --git a/src/rdb/rdb/rdb.h b/src/rdb/rdb/rdb.h index 3541e6768..a2d0f0b5a 100644 --- a/src/rdb/rdb/rdb.h +++ b/src/rdb/rdb/rdb.h @@ -1014,6 +1014,26 @@ public: */ void set_image_str (const std::string &s); + /** + * @brief Gets the item comment + * + * The comment string is an arbitrary string attached to the item. + */ + const std::string &comment () const + { + return m_comment; + } + + /** + * @brief Sets the item comment + * + * The comment string is an arbitrary string attached to the item. + */ + void set_comment (const std::string &s) + { + m_comment = s; + } + /** * @brief Get the database reference */ @@ -1038,6 +1058,7 @@ private: id_type m_cell_id; id_type m_category_id; size_t m_multiplicity; + std::string m_comment; bool m_visited; std::vector m_tag_ids; Database *mp_database; @@ -1462,7 +1483,7 @@ public: * * This method is provided for persistency application only. It should not be used otherwise. */ - Cell (id_type id, const std::string &name, const std::string &variant); + Cell (id_type id, const std::string &name, const std::string &variant, const std::string &layout_name); /** * @brief Cell destructor @@ -1488,7 +1509,7 @@ public: } /** - * @brief Get the cell name + * @brief Gets the cell name */ const std::string &name () const { @@ -1496,7 +1517,7 @@ public: } /** - * @brief Set the name string (setter) + * @brief Sets the name string * * This method must not be used for items in the database to keep the database consistent. */ @@ -1506,7 +1527,7 @@ public: } /** - * @brief Get the variant id + * @brief Gets the variant id */ const std::string &variant () const { @@ -1514,7 +1535,7 @@ public: } /** - * @brief Set the variant string (setter) + * @brief Sets the variant string * * This method must not be used for items in the database to keep the database consistent. */ @@ -1523,6 +1544,24 @@ public: m_variant = v; } + /** + * @brief Gets the layout cell name + */ + const std::string &layout_name () const + { + return m_layout_name; + } + + /** + * @brief Sets the layout cell string + * + * This method must not be used for items in the database to keep the database consistent. + */ + void set_layout_name (const std::string &s) + { + m_layout_name = s; + } + /** * @brief Get the qualified name (name plus optionally the variant id separated by a colon) */ @@ -1600,6 +1639,7 @@ private: id_type m_id; std::string m_name; std::string m_variant; + std::string m_layout_name; size_t m_num_items; size_t m_num_items_visited; References m_references; @@ -2203,7 +2243,7 @@ public: */ Cell *create_cell (const std::string &name) { - return create_cell (name, std::string ()); + return create_cell (name, std::string (), std::string ()); } /** @@ -2212,8 +2252,11 @@ public: * A cell with name name/variant combination must not exist already. * If the variant string is empty, this method behaves the same as the * method without variant. + * + * "layout_name" is the name of the cell in the layout. If empty, the layout + * cell is assumed to be identical to "name". */ - Cell *create_cell (const std::string &name, const std::string &variant); + Cell *create_cell (const std::string &name, const std::string &variant, const std::string &layout_name); /** * @brief Get all variants registered for a given cell name (not qname!) @@ -2307,6 +2350,11 @@ public: */ void remove_item_tag (const Item *item, id_type tag); + /** + * @brief Sets the comment string of the item + */ + void set_item_comment (const Item *item, const std::string &comment); + #if defined(HAVE_QT) /** * @brief Set the image of an item diff --git a/src/rdb/rdb/rdbFile.cc b/src/rdb/rdb/rdbFile.cc index b845cfb92..d7575e839 100644 --- a/src/rdb/rdb/rdbFile.cc +++ b/src/rdb/rdb/rdbFile.cc @@ -91,7 +91,8 @@ make_rdb_structure (rdb::Database *rdb) tl::make_element_with_parent_ref (&rdb::Cells::begin, &rdb::Cells::end, &rdb::Cells::import_cell, "cell", tl::make_member (&rdb::Cell::name, &rdb::Cell::set_name, "name") + tl::make_member (&rdb::Cell::variant, &rdb::Cell::set_variant, "variant") + - tl::make_element_with_parent_ref (&rdb::Cell::references, &rdb::Cell::import_references, "references", + tl::make_member (&rdb::Cell::layout_name, &rdb::Cell::set_layout_name, "layout-name") + + tl::make_element_with_parent_ref (&rdb::Cell::references, &rdb::Cell::import_references, "references", tl::make_element_with_parent_ref (&rdb::References::begin, &rdb::References::end, &rdb::References::insert, "ref", tl::make_member (&rdb::Reference::parent_cell_qname, &rdb::Reference::set_parent_cell_qname, "parent") + tl::make_member (&rdb::Reference::trans_str, &rdb::Reference::set_trans_str, "trans") @@ -106,6 +107,7 @@ make_rdb_structure (rdb::Database *rdb) tl::make_member (&rdb::Item::cell_qname, &rdb::Item::set_cell_qname, "cell") + tl::make_member (&rdb::Item::visited, &rdb::Item::set_visited, "visited") + tl::make_member (&rdb::Item::multiplicity, &rdb::Item::set_multiplicity, "multiplicity") + + tl::make_member (&rdb::Item::comment, &rdb::Item::set_comment, "comment") + tl::make_member (&rdb::Item::image_str, &rdb::Item::set_image_str, "image") + tl::make_element (&rdb::Item::values, &rdb::Item::set_values, "values", tl::make_member (&rdb::Values::begin, &rdb::Values::end, &rdb::Values::add, "value", ValueConverter (rdb)) diff --git a/src/rdb/unit_tests/rdbTests.cc b/src/rdb/unit_tests/rdbTests.cc index 5665aa522..88b48676e 100644 --- a/src/rdb/unit_tests/rdbTests.cc +++ b/src/rdb/unit_tests/rdbTests.cc @@ -521,11 +521,11 @@ TEST(6) EXPECT_EQ (db.variants ("c1")[0], c1->id ()); EXPECT_EQ (db.variants ("c1")[1], c1a->id ()); - rdb::Cell *c1b = db.create_cell ("c1", "var"); + rdb::Cell *c1b = db.create_cell ("c1", "var", std::string ()); EXPECT_EQ (c1b->qname (), "c1:var") EXPECT_EQ (db.variants ("c1").size (), size_t (3)); - rdb::Cell *c2 = db.create_cell ("c2", "1027"); + rdb::Cell *c2 = db.create_cell ("c2", "1027", std::string ()); EXPECT_EQ (c2->qname (), "c2:1027"); EXPECT_EQ (db.variants ("c2").size (), size_t (1)); @@ -534,8 +534,9 @@ TEST(6) EXPECT_EQ (c2->qname (), "c2:1027") EXPECT_EQ (db.variants ("c2").size (), size_t (2)); - rdb::Cell *c2b = db.create_cell ("c2", "var"); + rdb::Cell *c2b = db.create_cell ("c2", "var", "c2$1"); EXPECT_EQ (c2b->qname (), "c2:var") + EXPECT_EQ (c2b->layout_name (), "c2$1") rdb::Cell *c2c = db.create_cell ("c2"); EXPECT_EQ (c2c->qname (), "c2:2"); diff --git a/testdata/ruby/rdbTest.rb b/testdata/ruby/rdbTest.rb index abc40519f..eb99bd859 100644 --- a/testdata/ruby/rdbTest.rb +++ b/testdata/ruby/rdbTest.rb @@ -76,16 +76,22 @@ class RDB_TestClass < TestBase assert_equal(cell.name, "cell_name") assert_equal(cell.rdb_id, 1) - cell2 = db.create_cell("cell_name", "var1") + cell2 = db.create_cell("new_cell", "var1") + assert_equal(cell2.name, "new_cell") + assert_equal(cell2.layout_name, "") + assert_equal(cell2.qname, "new_cell:var1") + + cell2 = db.create_cell("cell_name", "var1", "cell_name$1") assert_equal(cell.name, "cell_name") assert_equal(cell.qname, "cell_name:1") assert_equal(db.cell_by_qname("cell_name:1").rdb_id, cell.rdb_id) assert_equal(db.cell_by_id(cell.rdb_id).rdb_id, cell.rdb_id) assert_equal(cell2.name, "cell_name") + assert_equal(cell2.layout_name, "cell_name$1") assert_equal(cell2.qname, "cell_name:var1") assert_equal(db.cell_by_qname("cell_name:var1").rdb_id, cell2.rdb_id) assert_equal(db.cell_by_id(cell2.rdb_id).rdb_id, cell2.rdb_id) - assert_equal(cell2.rdb_id, 2) + assert_equal(cell2.rdb_id, 3) assert_equal(cell.num_items, 0) assert_equal(cell2.num_items, 0) assert_equal(cell.num_items_visited, 0) @@ -98,19 +104,19 @@ class RDB_TestClass < TestBase cc = [] db.each_cell { |c| cc.push(c) } - assert_equal(cc.size, 2) + assert_equal(cc.size, 3) assert_equal(cc[0].rdb_id, cell.rdb_id) - assert_equal(cc[1].rdb_id, cell2.rdb_id) + assert_equal(cc[2].rdb_id, cell2.rdb_id) cat = db.create_category("cat") assert_equal(cat.database.inspect, db.inspect) assert_equal(cat.name, "cat") - assert_equal(cat.rdb_id, 3) + assert_equal(cat.rdb_id, 4) assert_equal(cat.path, "cat") cats = db.create_category(cat, "subcat") assert_equal(cats.name, "subcat") - assert_equal(cats.rdb_id, 4) + assert_equal(cats.rdb_id, 5) assert_equal(cats.path, "cat.subcat") assert_equal(cats.parent.rdb_id, cat.rdb_id) @@ -425,6 +431,10 @@ class RDB_TestClass < TestBase assert_equal(item.image_str, "") assert_equal(item.has_image?, false) + assert_equal(item.comment, "") + item.comment = "abc" + assert_equal(item.comment, "abc") + # can actually by any string, but only base64-encoded PNG images make sense is="iVBORw0KGgoAAAANSUhEUgAAACoAAAA0CAIAAABzfT3nAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAA0SAAANOgHo3ZneAAAA3UlEQVRYhe2WwQ3DIAxFoco8XaGZIaeO43FyYgZYgYXcQ6SWuDGgBhWq/qccIvGCEd9SbAwAAPSGaW2lFR2rfWDpXrPpSe2SP10fvnn/PZHZH9IwbKFVZZ/Z6wMtZcjW02Bn2FVpZYdWdkr2nvh23S2FyDNJuVITpwmRjTGbNr0v20U5byNtJuuJt/fO2f93+UlbEJl5UjVPr3Y71EQ/PoPPlU+lDJtWlCt3GwCMG33BuJGAcWMEMG6c1jBudCyf/nzV8nbZPRohclFLHdGbZ8eNSjN1fmf0AACA1jwA4hKxu4C6P7EAAAAASUVORK5CYII=" item.image_str=is