Reworking technology API a little: providing a way to register a new technology object, clarification of doc

This commit is contained in:
Matthias Koefferlein 2023-11-25 16:22:44 +01:00
parent 9565a55a3b
commit 0ea2610bf4
7 changed files with 96 additions and 50 deletions

View File

@ -80,7 +80,7 @@ Technologies::instance ()
static tl::XMLElementList xml_elements ()
{
return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add, "technology",
return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add_void, "technology",
Technology::xml_elements ()
);
}
@ -92,7 +92,7 @@ Technologies::to_xml () const
db::Technologies copy;
for (const_iterator t = begin (); t != end (); ++t) {
if (t->is_persisted ()) {
copy.add (new Technology (*t));
copy.add (*t);
}
}
@ -110,7 +110,7 @@ Technologies::load_from_xml (const std::string &s)
db::Technologies copy;
for (const_iterator t = begin (); t != end (); ++t) {
if (! t->is_persisted ()) {
copy.add (new Technology (*t));
copy.add (*t);
}
}
@ -121,34 +121,31 @@ Technologies::load_from_xml (const std::string &s)
*this = copy;
}
void
Technologies::add_tech (Technology *tech, bool replace_same)
db::Technology *
Technologies::add_tech (const Technology &tech, bool replace_same)
{
if (! tech) {
return;
}
std::unique_ptr<Technology> tech_ptr (tech);
Technology *t = 0;
for (tl::stable_vector<Technology>::iterator i = m_technologies.begin (); !t && i != m_technologies.end (); ++i) {
if (i->name () == tech->name ()) {
if (i->name () == tech.name ()) {
t = i.operator-> ();
}
}
if (t) {
if (replace_same) {
*t = *tech;
*t = tech;
} else {
throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech->name ());
throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech.name ());
}
} else {
m_technologies.push_back (tech_ptr.release ());
tech->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
t = new Technology (tech);
m_technologies.push_back (t);
t->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
}
technologies_changed ();
return t;
}
void

View File

@ -121,24 +121,34 @@ public:
/**
* @brief Adds a technology to the setup
*
* The container becomes owner of the technology object.
* Replaces a technology with the name of the given technology.
* @return A reference to the new Technology object
*
* If a technology with the given name already exists, it is replaced.
*/
void add (Technology *technology)
db::Technology *add (const Technology &technology)
{
add_tech (technology, true /*replace*/);
return add_tech (technology, true /*replace*/);
}
/**
* @brief Adds a technology with a new name
*
* @return A reference to the new Technology object
*
* Like \add, but throws an exception if a technology with this name
* already exists. Takes over ownership over the technology object.
* The technology object is discarded if an exception is thrown.
* already exists.
*/
void add_new (Technology *technology)
db::Technology *add_new (const Technology &technology)
{
add_tech (technology, false /*throws exception on same name*/);
return add_tech (technology, false /*throws exception on same name*/);
}
/**
* @brief Same as add, but no return value (for XML binding)
*/
void add_void (const Technology &technology)
{
add (technology);
}
/**
@ -244,7 +254,7 @@ private:
bool m_changed;
bool m_in_update;
void add_tech (Technology *technology, bool replace_same);
Technology *add_tech(const Technology &technology, bool replace_same);
};
/**

View File

@ -45,10 +45,14 @@ static db::Technology *technology_by_name (const std::string &name)
static db::Technology *create_technology (const std::string &name)
{
db::Technology *tech = new db::Technology ();
tech->set_name (name);
db::Technologies::instance ()->add_new (tech);
return tech;
db::Technology tech;
tech.set_name (name);
return db::Technologies::instance ()->add_new (tech);
}
static db::Technology *register_technology (const db::Technology &tech)
{
return db::Technologies::instance ()->add_new (tech);
}
static void remove_technology (const std::string &name)
@ -291,10 +295,24 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
gsi::method ("create_technology", &create_technology, gsi::arg ("name"),
"@brief Creates a new (empty) technology with the given name\n"
"\n"
"The new technology is already registered in the system.\n"
"\n"
"This method returns a reference to the new technology."
) +
gsi::method ("register_technology", &register_technology, gsi::arg ("tech"),
"@brief Registers a technology in the system\n"
"\n"
"Only after a technology is registered, it can be used in the system, e.g. by "
"specifying its name in \\Layout#technology_name. While \\create_technology already registers "
"the technology, this method allows registering a Technology object that has created in other ways.\n"
"\n"
"This method returns a reference to the new technology object which is a copy of the argument. "
"\\remove_technology can be used to remove a technology registered by this method.\n"
"\n"
"This method has been introduced in version 0.28.14."
) +
gsi::method ("remove_technology", &remove_technology, gsi::arg ("name"),
"@brief Removes the technology with the given name\n"
"@brief Removes the technology with the given name from the system\n"
) +
gsi::method ("technologies_to_xml", &technologies_to_xml,
"@brief Returns a XML representation of all technologies registered in the system\n"
@ -317,12 +335,13 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
gsi::method ("technologies_from_xml", &technologies_from_xml, gsi::arg ("xml"),
"@brief Loads the technologies from a XML representation\n"
"\n"
"See \\technologies_to_xml for details. This method is the corresponding setter."
"See \\technologies_to_xml for details."
) +
gsi::method ("technology_from_xml", &technology_from_xml, gsi::arg ("xml"),
"@brief Loads the technology from a XML representation\n"
"\n"
"See \\technology_to_xml for details."
"See \\technology_to_xml for details. Note that this function will create "
"a new Technology object which is not registered in the system. See \\Technology#register for details."
) +
gsi::method_ext ("component_names", &get_component_names,
"@brief Gets the names of all components available for \\component"
@ -338,6 +357,21 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
"definitions are returned with \\technology_by_name. Use \\create_technology to register "
"new technologies and \\remove_technology to delete technologies.\n"
"\n"
"Note that a Technology object needs to be registered in the system, before its name "
"can be used to specify a technology, for example in \\Layout#technology_name. "
"Technology objects created by \\create_technology are automatically registered. "
"If you create a Technology object directly, you need to register it explicitly:"
"\n"
"@code\n"
"tech = RBA::Technology::new\n"
"tech.load(\"mytech.lyt\")\n"
"RBA::Technology::register(tech)\n"
"@/code\n"
"\n"
"Note that in the latter example, an exception will be thrown if a technology with the same "
"name already exists. Also note, that \\Technology#register will register a copy of the "
"object, so modifying it after registration will not have any effect.\n"
"\n"
"The Technology class has been introduced in version 0.25.\n"
);

View File

@ -775,13 +775,13 @@ BEGIN_PROTECTED
}
}
db::Technology *nt = new db::Technology (*t);
db::Technology nt (*t);
nt->set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt"))));
nt->set_default_base_path (tl::to_string (tech_dir.absolutePath ()));
nt->set_persisted (false);
nt->set_name (tl::to_string (tn));
nt->set_description (std::string ());
nt.set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt"))));
nt.set_default_base_path (tl::to_string (tech_dir.absolutePath ()));
nt.set_persisted (false);
nt.set_name (tl::to_string (tn));
nt.set_description (std::string ());
m_technologies.add (nt);
update_tech_tree ();
@ -900,12 +900,7 @@ BEGIN_PROTECTED
db::Technology t;
t.load (fn);
if (m_technologies.has_technology (t.name ())) {
*m_technologies.technology_by_name (t.name ()) = t;
} else {
m_technologies.add (new db::Technology (t));
}
m_technologies.add (t);
update_tech_tree ();
select_tech (*m_technologies.technology_by_name (t.name ()));

View File

@ -536,7 +536,7 @@ TechnologyController::rescan (db::Technologies &technologies)
technologies.clear ();
for (db::Technologies::const_iterator t = current.begin (); t != current.end (); ++t) {
if (t->is_persisted ()) {
technologies.add (new db::Technology (*t));
technologies.add (*t);
}
}
@ -596,7 +596,7 @@ TechnologyController::rescan (db::Technologies &technologies)
t.set_persisted (false); // don't save that one in the configuration
t.set_readonly (readonly || ! QFileInfo (dir.filePath (*lf)).isWritable ());
t.set_grain_name (grain_name);
technologies.add (new db::Technology (t));
technologies.add (t);
} catch (tl::Exception &ex) {
tl::warn << tl::to_string (QObject::tr ("Unable to auto-import technology file ")) << tl::to_string (*lf) << ": " << ex.msg ();
@ -608,14 +608,14 @@ TechnologyController::rescan (db::Technologies &technologies)
for (std::vector<db::Technology>::const_iterator t = m_temp_tech.begin (); t != m_temp_tech.end (); ++t) {
db::Technology *tech = new db::Technology (*t);
if (tl::verbosity () >= 20) {
tl::info << "Registering special technology from " << tech->tech_file_path () << " as " << tech->name ();
tl::info << "Registering special technology from " << t->tech_file_path () << " as " << t->name ();
}
db::Technology *tech = technologies.add (*t);
tech->set_persisted (false); // don't save that one in the configuration
tech->set_tech_file_path (std::string ()); // don't save to a file either
tech->set_readonly (true); // don't edit
technologies.add (tech);
}
}

View File

@ -137,6 +137,7 @@ RUBYTEST (dbTilingProcessorTest, "dbTilingProcessorTest.rb")
RUBYTEST (dbTransTest, "dbTransTest.rb")
RUBYTEST (dbVectorTest, "dbVectorTest.rb")
RUBYTEST (dbUtilsTests, "dbUtilsTests.rb")
RUBYTEST (dbTechnologies, "dbTechnologies.rb")
RUBYTEST (edtTest, "edtTest.rb")
RUBYTEST (extNetTracer, "extNetTracer.rb")
RUBYTEST (imgObject, "imgObject.rb")
@ -147,7 +148,6 @@ RUBYTEST (layMacro, "layMacro.rb")
RUBYTEST (layMenuTest, "layMenuTest.rb")
RUBYTEST (layPixelBuffer, "layPixelBuffer.rb")
RUBYTEST (laySession, "laySession.rb")
RUBYTEST (layTechnologies, "layTechnologies.rb")
RUBYTEST (laySaveLayoutOptions, "laySaveLayoutOptions.rb")
#if defined(HAVE_QT) && defined(HAVE_QTBINDINGS)
RUBYTEST (qtbinding, "qtbinding.rb")

View File

@ -73,6 +73,16 @@ END
RBA::Technology::remove_technology("MINE2")
assert_equal(RBA::Technology::technology_names.inspect, '[""]')
# registration
tech = RBA::Technology::new
tech.name = "NEW"
tech.dbu = 0.5
tech_new = RBA::Technology::register_technology(tech)
tech._destroy
assert_equal(RBA::Technology::technology_names.inspect, '["", "NEW"]')
assert_equal(tech_new.dbu, 0.5)
assert_equal(tech_new.name, "NEW")
end
def test_2