mirror of https://github.com/KLayout/klayout.git
WIP (also for other issue #2172)
- New virtual method "reload" for Library - Implementing that for file-based libraries - Integrating that into "refresh" - GSI binding for Library#rename, Library#unregister - Trigger changed event on Library#unregister - Library#_destroy will unregister the library - Typos fixed
This commit is contained in:
parent
ec5de0ffe8
commit
b3ec482eb8
|
|
@ -145,9 +145,25 @@ Library::is_retired (const db::cell_index_type library_cell_index) const
|
||||||
return (i != m_refcount.end () && j != m_retired_count.end () && i->second == j->second);
|
return (i != m_refcount.end () && j != m_retired_count.end () && i->second == j->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Library::rename (const std::string &name)
|
||||||
|
{
|
||||||
|
if (name != get_name () && db::LibraryManager::initialized ()) {
|
||||||
|
|
||||||
|
// if the name changed, reregister the library under the new name
|
||||||
|
db::LibraryManager::instance ().unregister_lib (this);
|
||||||
|
set_name (name);
|
||||||
|
db::LibraryManager::instance ().register_lib (this);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Library::refresh ()
|
Library::refresh ()
|
||||||
{
|
{
|
||||||
|
std::string name = reload ();
|
||||||
|
rename (name);
|
||||||
|
|
||||||
layout ().refresh ();
|
layout ().refresh ();
|
||||||
remap_to (this);
|
remap_to (this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,20 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ~Library ();
|
virtual ~Library ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called to reload the library
|
||||||
|
*
|
||||||
|
* If the library is a file-based one, this method can be reimplemented to reload
|
||||||
|
* the file. This method must not change the name of the library, but return a new
|
||||||
|
* name in case it has changed.
|
||||||
|
*
|
||||||
|
* @return The new name of the library
|
||||||
|
*/
|
||||||
|
virtual std::string reload ()
|
||||||
|
{
|
||||||
|
return get_name ();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The layout object
|
* @brief The layout object
|
||||||
*
|
*
|
||||||
|
|
@ -211,6 +225,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void refresh ();
|
void refresh ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Renames the library
|
||||||
|
*
|
||||||
|
* Unlike "set_name", this method will take care of properly re-registering the library
|
||||||
|
* under the new name.
|
||||||
|
*/
|
||||||
|
void rename (const std::string &name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remap the library proxies to a different library
|
* @brief Remap the library proxies to a different library
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,9 @@ LibraryManager::unregister_lib (Library *library)
|
||||||
|
|
||||||
library->remap_to (0);
|
library->remap_to (0);
|
||||||
library->set_id (std::numeric_limits<lib_id_type>::max ());
|
library->set_id (std::numeric_limits<lib_id_type>::max ());
|
||||||
|
|
||||||
|
// issue the change notification
|
||||||
|
changed_event ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,11 @@ static void register_lib (db::Library *lib, const std::string &name)
|
||||||
db::LibraryManager::instance ().register_lib (lib);
|
db::LibraryManager::instance ().register_lib (lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void unregister_lib (db::Library *lib)
|
||||||
|
{
|
||||||
|
db::LibraryManager::instance ().unregister_lib (lib);
|
||||||
|
}
|
||||||
|
|
||||||
static void delete_lib (db::Library *lib)
|
static void delete_lib (db::Library *lib)
|
||||||
{
|
{
|
||||||
db::LibraryManager::instance ().delete_lib (lib);
|
db::LibraryManager::instance ().delete_lib (lib);
|
||||||
|
|
@ -97,7 +102,7 @@ static std::string get_technology (db::Library *lib)
|
||||||
static void destroy_lib (db::Library *lib)
|
static void destroy_lib (db::Library *lib)
|
||||||
{
|
{
|
||||||
if (db::LibraryManager::instance ().lib_ptr_by_name (lib->get_name ()) == lib) {
|
if (db::LibraryManager::instance ().lib_ptr_by_name (lib->get_name ()) == lib) {
|
||||||
// Library is registered -> do not delete
|
delete_lib (lib);
|
||||||
} else {
|
} else {
|
||||||
delete lib;
|
delete lib;
|
||||||
}
|
}
|
||||||
|
|
@ -105,31 +110,51 @@ static void destroy_lib (db::Library *lib)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
class LibraryClass
|
class LibraryClass
|
||||||
: public Class<db::Library>
|
: public gsi::Class<Base>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LibraryClass (const char *module, const char *name, const gsi::Methods &methods, const char *description)
|
LibraryClass (const char *module, const char *name, const gsi::Methods &methods, const char *description)
|
||||||
: Class<db::Library> (module, name, methods, description)
|
: gsi::Class<Base> (module, name, methods, description)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template <class B>
|
||||||
|
LibraryClass (const gsi::Class<B> &base, const char *module, const char *name, const gsi::Methods &methods, const char *description)
|
||||||
|
: gsi::Class<Base> (base, module, name, methods, description)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void destroy (void *p) const
|
virtual void destroy (void *p) const
|
||||||
{
|
{
|
||||||
db::Library *lib = reinterpret_cast<db::Library *> (p);
|
Base *lib = reinterpret_cast<Base *> (p);
|
||||||
destroy_lib (lib);
|
destroy_lib (lib);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LibraryImpl
|
||||||
|
: public db::Library
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LibraryImpl () : db::Library () { }
|
||||||
|
|
||||||
|
virtual std::string reload ()
|
||||||
|
{
|
||||||
|
if (cb_reload.can_issue ()) {
|
||||||
|
return cb_reload.issue<db::Library, std::string> (&db::Library::reload);
|
||||||
|
} else {
|
||||||
|
return db::Library::reload ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsi::Callback cb_reload;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryClass decl_Library ("db", "Library",
|
LibraryClass<db::Library> decl_Library ("db", "LibraryBase",
|
||||||
gsi::constructor ("new", &new_lib,
|
|
||||||
"@brief Creates a new, empty library"
|
|
||||||
) +
|
|
||||||
gsi::method ("library_by_name", &library_by_name, gsi::arg ("name"), gsi::arg ("for_technology", std::string (), "unspecific"),
|
gsi::method ("library_by_name", &library_by_name, gsi::arg ("name"), gsi::arg ("for_technology", std::string (), "unspecific"),
|
||||||
"@brief Gets a library by name\n"
|
"@brief Gets a library by name\n"
|
||||||
"Returns the library object for the given name. If the name is not a valid\n"
|
"Returns the library object for the given name. If the name is not a valid library name, nil is returned.\n"
|
||||||
"library name, nil is returned.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"Different libraries can be registered under the same names for different technologies. When a technology name is given in 'for_technologies', "
|
"Different libraries can be registered under the same names for different technologies. When a technology name is given in 'for_technologies', "
|
||||||
"the first library matching this technology is returned. If no technology is given, the first library is returned.\n"
|
"the first library matching this technology is returned. If no technology is given, the first library is returned.\n"
|
||||||
|
|
@ -166,6 +191,22 @@ LibraryClass decl_Library ("db", "Library",
|
||||||
"\n"
|
"\n"
|
||||||
"The technology specific behaviour has been introduced in version 0.27."
|
"The technology specific behaviour has been introduced in version 0.27."
|
||||||
) +
|
) +
|
||||||
|
gsi::method_ext ("unregister", &unregister_lib,
|
||||||
|
"@brief Unregisters the library\n"
|
||||||
|
"\n"
|
||||||
|
"Unregisters the library from the system. This will break all references of cells "
|
||||||
|
"using this library and make them 'defunct'.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.30.5."
|
||||||
|
) +
|
||||||
|
gsi::method ("rename", &db::Library::rename, gsi::arg ("name"),
|
||||||
|
"@brief Renames the library\n"
|
||||||
|
"\n"
|
||||||
|
"Re-registers the library under a new name. Note that this will not change library references - "
|
||||||
|
"i.e. references to the old name will become invalid after calling this method.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.30.5."
|
||||||
|
) +
|
||||||
gsi::method_ext ("delete", &delete_lib,
|
gsi::method_ext ("delete", &delete_lib,
|
||||||
"@brief Deletes the library\n"
|
"@brief Deletes the library\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -176,7 +217,7 @@ LibraryClass decl_Library ("db", "Library",
|
||||||
) +
|
) +
|
||||||
gsi::method ("name", &db::Library::get_name,
|
gsi::method ("name", &db::Library::get_name,
|
||||||
"@brief Returns the libraries' name\n"
|
"@brief Returns the libraries' name\n"
|
||||||
"The name is set when the library is registered and cannot be changed\n"
|
"The name is set when the library is registered. To change it use \\rename.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method ("id", &db::Library::get_id,
|
gsi::method ("id", &db::Library::get_id,
|
||||||
"@brief Returns the library's ID\n"
|
"@brief Returns the library's ID\n"
|
||||||
|
|
@ -240,9 +281,27 @@ LibraryClass decl_Library ("db", "Library",
|
||||||
"@brief Updates all layouts using this library.\n"
|
"@brief Updates all layouts using this library.\n"
|
||||||
"This method will retire cells or update layouts in the attached clients.\n"
|
"This method will retire cells or update layouts in the attached clients.\n"
|
||||||
"It will also recompute the PCells inside the library. "
|
"It will also recompute the PCells inside the library. "
|
||||||
|
"Starting with version 0.30.5, this method will also call 'reload' on all libraries to "
|
||||||
|
"refresh cells located in external files.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.27.8."
|
"This method has been introduced in version 0.27.8."
|
||||||
),
|
),
|
||||||
|
"@hide"
|
||||||
|
);
|
||||||
|
|
||||||
|
LibraryClass<LibraryImpl> decl_LibraryImpl (decl_Library, "db", "Library",
|
||||||
|
gsi::constructor ("new", &new_lib,
|
||||||
|
"@brief Creates a new, empty library"
|
||||||
|
) +
|
||||||
|
gsi::callback ("reload", &LibraryImpl::reload, &LibraryImpl::cb_reload,
|
||||||
|
"@brief Reloads resources for the library.\n"
|
||||||
|
"Reimplement this method if you like to reload resources the library was created from - "
|
||||||
|
"for example layout files.\n"
|
||||||
|
"\n"
|
||||||
|
"@return The new name of the library or the original name if it did not change.\n"
|
||||||
|
"\n"
|
||||||
|
"This method is called on \\refresh. It was introduced in version 0.30.5.\n"
|
||||||
|
),
|
||||||
"@brief A Library \n"
|
"@brief A Library \n"
|
||||||
"\n"
|
"\n"
|
||||||
"A library is basically a wrapper around a layout object. The layout object\n"
|
"A library is basically a wrapper around a layout object. The layout object\n"
|
||||||
|
|
|
||||||
|
|
@ -1034,7 +1034,7 @@ Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDevic
|
||||||
|
|
||||||
Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_dbEqualDeviceParameters, "db", "GenericDeviceParameterCompare",
|
Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_dbEqualDeviceParameters, "db", "GenericDeviceParameterCompare",
|
||||||
gsi::callback ("less", &GenericDeviceParameterCompare::less, &GenericDeviceParameterCompare::cb_less, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
gsi::callback ("less", &GenericDeviceParameterCompare::less, &GenericDeviceParameterCompare::cb_less, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
||||||
"@brief Compares the parameters of two devices for a begin less than b. "
|
"@brief Compares the parameters of two devices for a begin less than b.\n"
|
||||||
"Returns true, if the parameters of device a are considered less than those of device b."
|
"Returns true, if the parameters of device a are considered less than those of device b."
|
||||||
"The 'less' implementation needs to ensure strict weak ordering. Specifically, less(a,b) == false and less(b,a) implies that a is equal to b and "
|
"The 'less' implementation needs to ensure strict weak ordering. Specifically, less(a,b) == false and less(b,a) implies that a is equal to b and "
|
||||||
"less(a,b) == true implies that less(b,a) is false and vice versa. If not, an internal error "
|
"less(a,b) == true implies that less(b,a) is false and vice versa. If not, an internal error "
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,53 @@
|
||||||
#include "dbReader.h"
|
#include "dbReader.h"
|
||||||
#include "tlLog.h"
|
#include "tlLog.h"
|
||||||
#include "tlStream.h"
|
#include "tlStream.h"
|
||||||
|
#include "tlFileUtils.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FileBasedLibrary
|
||||||
|
: public db::Library
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileBasedLibrary (const std::string &path)
|
||||||
|
: db::Library (), m_path (path)
|
||||||
|
{
|
||||||
|
set_description (tl::filename (path));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string reload ()
|
||||||
|
{
|
||||||
|
std::string name = tl::basename (m_path);
|
||||||
|
|
||||||
|
layout ().clear ();
|
||||||
|
|
||||||
|
tl::InputStream stream (m_path);
|
||||||
|
db::Reader reader (stream);
|
||||||
|
reader.read (layout ());
|
||||||
|
|
||||||
|
// Use the libname if there is one
|
||||||
|
db::Layout::meta_info_name_id_type libname_name_id = layout ().meta_info_name_id ("libname");
|
||||||
|
for (db::Layout::meta_info_iterator m = layout ().begin_meta (); m != layout ().end_meta (); ++m) {
|
||||||
|
if (m->first == libname_name_id && ! m->second.value.is_nil ()) {
|
||||||
|
name = m->second.value.to_string ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
LibraryController::LibraryController ()
|
LibraryController::LibraryController ()
|
||||||
: m_file_watcher (0),
|
: m_file_watcher (0),
|
||||||
dm_sync_files (this, &LibraryController::sync_files)
|
dm_sync_files (this, &LibraryController::sync_files)
|
||||||
|
|
@ -166,7 +207,6 @@ LibraryController::sync_files ()
|
||||||
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
||||||
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
||||||
|
|
||||||
std::string filename = tl::to_string (*im);
|
|
||||||
std::string lib_path = tl::to_string (lp.absoluteFilePath (*im));
|
std::string lib_path = tl::to_string (lp.absoluteFilePath (*im));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -187,26 +227,13 @@ LibraryController::sync_files ()
|
||||||
|
|
||||||
if (needs_load) {
|
if (needs_load) {
|
||||||
|
|
||||||
std::unique_ptr<db::Library> lib (new db::Library ());
|
std::unique_ptr<db::Library> lib (new FileBasedLibrary (lib_path));
|
||||||
lib->set_description (filename);
|
|
||||||
if (! p->second.empty ()) {
|
if (! p->second.empty ()) {
|
||||||
lib->set_technology (p->second);
|
lib->set_technology (p->second);
|
||||||
}
|
}
|
||||||
lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
|
|
||||||
|
|
||||||
tl::log << "Reading library '" << lib_path << "'";
|
tl::log << "Reading library '" << lib_path << "'";
|
||||||
tl::InputStream stream (lib_path);
|
lib->set_name (lib->reload ());
|
||||||
db::Reader reader (stream);
|
|
||||||
reader.read (lib->layout ());
|
|
||||||
|
|
||||||
// Use the libname if there is one
|
|
||||||
db::Layout::meta_info_name_id_type libname_name_id = lib->layout ().meta_info_name_id ("libname");
|
|
||||||
for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) {
|
|
||||||
if (m->first == libname_name_id && ! m->second.value.is_nil ()) {
|
|
||||||
lib->set_name (m->second.value.to_string ());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! p->second.empty ()) {
|
if (! p->second.empty ()) {
|
||||||
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'";
|
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue