mirror of https://github.com/KLayout/klayout.git
Technology specific libraries
Libraries now carry a technology association and only libraries associated with the current technology can be selected. To enforce proper update, cancel() will be used upon change of technology. This avoids side effects when changing the technology without notifying the library selection widgets. The MainWindow::cancel method has been generalized to cover the functionality of cm_cancel without the exception handling.
This commit is contained in:
parent
01e5c607fc
commit
1091ea6d5b
|
|
@ -101,6 +101,25 @@ public:
|
|||
m_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the technology name this library is associated with
|
||||
*
|
||||
* If this attribute is non-empty, the library is selected only when the given technology is
|
||||
* used for the layout.
|
||||
*/
|
||||
const std::string &get_technology () const
|
||||
{
|
||||
return m_technology;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the technology name this library is associated with
|
||||
*/
|
||||
void set_technology (const std::string &t)
|
||||
{
|
||||
m_technology = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Getter for the description property
|
||||
*/
|
||||
|
|
@ -153,6 +172,7 @@ public:
|
|||
private:
|
||||
std::string m_name;
|
||||
std::string m_description;
|
||||
std::string m_technology;
|
||||
lib_id_type m_id;
|
||||
db::Layout m_layout;
|
||||
std::map<db::Layout *, int> m_referrers;
|
||||
|
|
|
|||
|
|
@ -110,11 +110,25 @@ Class<db::Library> decl_Library ("Library",
|
|||
gsi::method ("description", &db::Library::get_description,
|
||||
"@brief Returns the libraries' description text\n"
|
||||
) +
|
||||
gsi::method ("description=", &db::Library::set_description,
|
||||
gsi::method ("description=", &db::Library::set_description,
|
||||
"@brief Sets the libraries' description text\n"
|
||||
"@args description\n"
|
||||
) +
|
||||
gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout,
|
||||
gsi::method ("technology", &db::Library::get_technology,
|
||||
"@brief Returns name of the technology the library is associated with\n"
|
||||
"If this attribute is a non-empty string, this library is only offered for "
|
||||
"selection if the current layout uses this technology.\n"
|
||||
"\n"
|
||||
"This attribute has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("technology=", &db::Library::set_technology,
|
||||
"@brief sets the name of the technology the library is associated with\n"
|
||||
"@args technology\n"
|
||||
"\n"
|
||||
"See \\technology for details. "
|
||||
"This attribute has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout,
|
||||
"@brief The layout object where the cells reside that this library defines (const version)\n"
|
||||
) +
|
||||
gsi::method ("layout", (db::Layout &(db::Library::*)()) &db::Library::layout,
|
||||
|
|
|
|||
|
|
@ -691,6 +691,11 @@ EditorOptionsInst::setup (lay::Plugin *root)
|
|||
m_cv_index = lay::LayoutView::current ()->active_cellview_index ();
|
||||
}
|
||||
mp_ui->lib_cbx->update_list ();
|
||||
if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) {
|
||||
mp_ui->lib_cbx->set_technology_filter (lay::LayoutView::current ()->cellview (m_cv_index)->tech_name (), true);
|
||||
} else {
|
||||
mp_ui->lib_cbx->set_technology_filter (std::string (), false);
|
||||
}
|
||||
|
||||
// cell name
|
||||
std::string s;
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ InstPropertiesPage::update ()
|
|||
const db::Cell &def_cell = def_layout->cell (def_cell_index);
|
||||
|
||||
std::pair<db::Library *, db::cell_index_type> dl = def_layout->defining_library (def_cell_index);
|
||||
lib_cbx->set_technology_filter (cv->tech_name (), true);
|
||||
lib_cbx->set_current_library (dl.first);
|
||||
if (dl.first) {
|
||||
def_layout = &dl.first->layout ();
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "layLibraryController.h"
|
||||
#include "layTechnology.h"
|
||||
#include "layApplication.h"
|
||||
#include "laySaltController.h"
|
||||
#include "layConfig.h"
|
||||
|
|
@ -125,76 +126,96 @@ LibraryController::sync_files ()
|
|||
|
||||
std::map<std::string, std::pair<std::string, QDateTime> > new_lib_files;
|
||||
|
||||
std::vector<std::string> paths = lay::Application::instance ()->klayout_path ();
|
||||
// build a list of paths vs. technology
|
||||
std::vector<std::pair<std::string, std::string> > paths;
|
||||
|
||||
std::vector<std::string> klayout_path = lay::Application::instance ()->klayout_path ();
|
||||
for (std::vector<std::string>::const_iterator p = klayout_path.begin (); p != klayout_path.end (); ++p) {
|
||||
paths.push_back (std::make_pair (*p, std::string ()));
|
||||
}
|
||||
|
||||
// add the salt grains as potential sources for library definitions
|
||||
|
||||
lay::SaltController *sc = lay::SaltController::instance ();
|
||||
if (sc) {
|
||||
for (lay::Salt::flat_iterator g = sc->salt ().begin_flat (); g != sc->salt ().end_flat (); ++g) {
|
||||
paths.push_back ((*g)->path ());
|
||||
paths.push_back (std::make_pair ((*g)->path (), std::string ()));
|
||||
}
|
||||
}
|
||||
|
||||
// add the technologies as potential sources for library definitions
|
||||
|
||||
for (lay::Technologies::iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) {
|
||||
if (! t->base_path ().empty ()) {
|
||||
paths.push_back (std::make_pair (t->base_path (), t->name ()));
|
||||
}
|
||||
}
|
||||
|
||||
// scan for libraries
|
||||
|
||||
for (std::vector <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
|
||||
for (std::vector <std::pair<std::string, std::string> >::const_iterator p = paths.begin (); p != paths.end (); ++p) {
|
||||
|
||||
QDir lp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("libraries"));
|
||||
m_file_watcher->add_file (tl::to_string (lp.absolutePath ()));
|
||||
QDir lp = QDir (tl::to_qstring (p->first)).filePath (tl::to_qstring ("libraries"));
|
||||
if (lp.exists ()) {
|
||||
|
||||
QStringList name_filters;
|
||||
name_filters << QString::fromUtf8 ("*");
|
||||
m_file_watcher->add_file (tl::to_string (lp.absolutePath ()));
|
||||
|
||||
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
||||
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
||||
QStringList name_filters;
|
||||
name_filters << QString::fromUtf8 ("*");
|
||||
|
||||
std::string filename = tl::to_string (*im);
|
||||
std::string lib_path = tl::to_string (lp.absoluteFilePath (*im));
|
||||
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
||||
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
||||
|
||||
try {
|
||||
std::string filename = tl::to_string (*im);
|
||||
std::string lib_path = tl::to_string (lp.absoluteFilePath (*im));
|
||||
|
||||
QFileInfo fi (tl::to_qstring (lib_path));
|
||||
try {
|
||||
|
||||
bool needs_load = false;
|
||||
std::map<std::string, std::pair<std::string, QDateTime> >::iterator ll = m_lib_files.find (lib_path);
|
||||
if (ll == m_lib_files.end ()) {
|
||||
needs_load = true;
|
||||
} else {
|
||||
if (fi.lastModified () > ll->second.second) {
|
||||
QFileInfo fi (tl::to_qstring (lib_path));
|
||||
|
||||
bool needs_load = false;
|
||||
std::map<std::string, std::pair<std::string, QDateTime> >::iterator ll = m_lib_files.find (lib_path);
|
||||
if (ll == m_lib_files.end ()) {
|
||||
needs_load = true;
|
||||
} else {
|
||||
new_lib_files.insert (*ll);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_load) {
|
||||
|
||||
std::auto_ptr<db::Library> lib (new db::Library ());
|
||||
lib->set_description (filename);
|
||||
lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
|
||||
|
||||
tl::log << "Reading library '" << filename << "'";
|
||||
tl::InputStream stream (lib_path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (lib->layout ());
|
||||
|
||||
// Use the libname if there is one
|
||||
for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) {
|
||||
if (m->name == "libname" && ! m->value.empty ()) {
|
||||
lib->set_name (m->value);
|
||||
break;
|
||||
if (fi.lastModified () > ll->second.second) {
|
||||
needs_load = true;
|
||||
} else {
|
||||
new_lib_files.insert (*ll);
|
||||
}
|
||||
}
|
||||
|
||||
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ())));
|
||||
if (needs_load) {
|
||||
|
||||
db::LibraryManager::instance ().register_lib (lib.release ());
|
||||
std::auto_ptr<db::Library> lib (new db::Library ());
|
||||
lib->set_description (filename);
|
||||
lib->set_technology (p->second);
|
||||
lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
|
||||
|
||||
tl::log << "Reading library '" << lib_path << "'";
|
||||
tl::InputStream stream (lib_path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (lib->layout ());
|
||||
|
||||
// Use the libname if there is one
|
||||
for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) {
|
||||
if (m->name == "libname" && ! m->value.empty ()) {
|
||||
lib->set_name (m->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << lib->get_technology () << "'";
|
||||
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ())));
|
||||
|
||||
db::LibraryManager::instance ().register_lib (lib.release ());
|
||||
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2608,7 +2608,6 @@ MainWindow::cm_cancel ()
|
|||
{
|
||||
BEGIN_PROTECTED
|
||||
cancel ();
|
||||
select_mode (lay::LayoutView::default_mode ());
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
|
|
@ -2618,8 +2617,6 @@ MainWindow::cm_cancel ()
|
|||
void
|
||||
MainWindow::cancel ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
// if any transaction is pending (this may happen when an operation threw an exception)
|
||||
// close transactions.
|
||||
if (m_manager.transacting ()) {
|
||||
|
|
@ -2630,7 +2627,7 @@ MainWindow::cancel ()
|
|||
(*vp)->cancel ();
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
select_mode (lay::LayoutView::default_mode ());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
<file alias="grain.xml">salt_templates/macro/grain.xml</file>
|
||||
</qresource>
|
||||
<qresource prefix="/salt_templates/macro/macros">
|
||||
<file alias="new_macro.lym">salt_templates/macro/macros/new_macro.lym</file>
|
||||
</qresource>
|
||||
<qresource prefix="/salt_templates/macro/doc">
|
||||
<file alias="readme.html">salt_templates/macro/doc/readme.html</file>
|
||||
</qresource>
|
||||
|
||||
<!-- pymacro template -->
|
||||
|
|
|
|||
|
|
@ -269,6 +269,11 @@ TechnologyController::menu_activated (const std::string &symbol) const
|
|||
{
|
||||
if (symbol == "technology_selector:apply_technology") {
|
||||
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) {
|
||||
// Cancels the current modes - changing the technology may make libraries unavailable
|
||||
// for example.
|
||||
if (mp_mw) {
|
||||
mp_mw->cancel ();
|
||||
}
|
||||
lay::LayoutView::current ()->active_cellview ()->apply_technology (m_current_technology);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<version>0.0</version>
|
||||
<title>Ruby Macro</title>
|
||||
<doc>This template provides a Ruby macro</doc>
|
||||
<doc-url/>
|
||||
<doc-url>doc/readme.html</doc-url>
|
||||
<url/>
|
||||
<license>GPLv3</license>
|
||||
<author/>
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ struct CellViewSelectionComboBoxPrivateData
|
|||
const lay::LayoutView *layout_view;
|
||||
};
|
||||
|
||||
CellViewSelectionComboBox::CellViewSelectionComboBox (QWidget * /*parent*/)
|
||||
CellViewSelectionComboBox::CellViewSelectionComboBox (QWidget *parent)
|
||||
: QComboBox (parent)
|
||||
{
|
||||
mp_private = new CellViewSelectionComboBoxPrivateData ();
|
||||
mp_private->layout_view = 0;
|
||||
|
|
@ -299,7 +300,8 @@ struct LayerSelectionComboBoxPrivateData
|
|||
int cv_index;
|
||||
};
|
||||
|
||||
LayerSelectionComboBox::LayerSelectionComboBox (QWidget * /*parent*/)
|
||||
LayerSelectionComboBox::LayerSelectionComboBox (QWidget *parent)
|
||||
: QComboBox (parent)
|
||||
{
|
||||
mp_private = new LayerSelectionComboBoxPrivateData ();
|
||||
mp_private->no_layer_available = false;
|
||||
|
|
@ -569,11 +571,22 @@ LayerSelectionComboBox::current_layer_props () const
|
|||
// -------------------------------------------------------------
|
||||
// LibrarySelectionComboBox implementation
|
||||
|
||||
LibrarySelectionComboBox::LibrarySelectionComboBox (QWidget * /*parent*/)
|
||||
LibrarySelectionComboBox::LibrarySelectionComboBox (QWidget *parent)
|
||||
: QComboBox (parent), m_tech_set (false)
|
||||
{
|
||||
update_list ();
|
||||
}
|
||||
|
||||
void
|
||||
LibrarySelectionComboBox::set_technology_filter (const std::string &tech, bool enabled)
|
||||
{
|
||||
if (m_tech != tech || m_tech_set != enabled) {
|
||||
m_tech = tech;
|
||||
m_tech_set = enabled;
|
||||
update_list ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LibrarySelectionComboBox::update_list ()
|
||||
{
|
||||
|
|
@ -585,12 +598,23 @@ LibrarySelectionComboBox::update_list ()
|
|||
|
||||
addItem (QObject::tr ("Local (no library)"), QVariant ());
|
||||
for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) {
|
||||
|
||||
db::Library *lib = db::LibraryManager::instance ().lib (l->second);
|
||||
if (! lib->get_description ().empty ()) {
|
||||
addItem (tl::to_qstring (lib->get_name () + " - " + lib->get_description ()), QVariant ((unsigned int) lib->get_id ()));
|
||||
} else {
|
||||
addItem (tl::to_qstring (lib->get_name ()), QVariant ((unsigned int) lib->get_id ()));
|
||||
if (! m_tech_set || lib->get_technology ().empty () || m_tech == lib->get_technology ()) {
|
||||
|
||||
std::string item_text = lib->get_name ();
|
||||
if (! lib->get_description ().empty ()) {
|
||||
item_text += " - " + lib->get_description ();
|
||||
}
|
||||
if (m_tech_set && !lib->get_technology ().empty ()) {
|
||||
item_text += " ";
|
||||
item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ())));
|
||||
}
|
||||
|
||||
addItem (tl::to_qstring (item_text), QVariant ((unsigned int) lib->get_id ()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_current_library (lib);
|
||||
|
|
|
|||
|
|
@ -147,6 +147,19 @@ public:
|
|||
* @brief Update the list of libraries
|
||||
*/
|
||||
void update_list ();
|
||||
|
||||
/**
|
||||
* @brief Sets the technology filter
|
||||
*
|
||||
* If a technology filter is set, only the libraries associated with the given
|
||||
* technology are shown. If enable is false, the technology name is ignored and
|
||||
* all libraries are shown.
|
||||
*/
|
||||
void set_technology_filter (const std::string &tech, bool enable);
|
||||
|
||||
private:
|
||||
std::string m_tech;
|
||||
bool m_tech_set;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue