diff --git a/src/lay/TechSetupDialog.ui b/src/lay/TechSetupDialog.ui index 490dc3654..56a85c4d9 100644 --- a/src/lay/TechSetupDialog.ui +++ b/src/lay/TechSetupDialog.ui @@ -115,6 +115,9 @@ :/add.png:/add.png + + true + @@ -126,6 +129,9 @@ :/clear.png:/clear.png + + true + diff --git a/src/lay/layMacroController.cc b/src/lay/layMacroController.cc index a069e6d1f..e9a086ed0 100644 --- a/src/lay/layMacroController.cc +++ b/src/lay/layMacroController.cc @@ -300,12 +300,21 @@ MacroController::sync_implicit_macros (bool ask_before_autorun) // Add additional places where the technologies define some macros std::map > tech_names_by_path; + std::map > grain_names_by_path; + std::set readonly_paths; for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) { if (! t->base_path ().empty ()) { QDir base_dir (tl::to_qstring (t->base_path ())); if (base_dir.exists ()) { - tech_names_by_path [tl::to_string (base_dir.absolutePath ())].push_back (t->name ()); + std::string path = tl::to_string (base_dir.absolutePath ()); + tech_names_by_path [path].push_back (t->name ()); + if (t->is_readonly ()) { + readonly_paths.insert (path); + } + if (! t->grain_name ().empty ()) { + grain_names_by_path [path].push_back (t->grain_name ()); + } } } } @@ -325,7 +334,17 @@ MacroController::sync_implicit_macros (bool ask_before_autorun) description = tl::to_string (tr ("Technologies %1").arg (tl::to_qstring (tl::join (t->second, ",")))); } - external_paths.push_back (ExternalPathDescriptor (tl::to_string (macro_dir.path ()), description, macro_categories () [c].first, lay::MacroCollection::TechFolder)); + std::map >::const_iterator gn = grain_names_by_path.find (t->first); + if (gn != grain_names_by_path.end ()) { + description += " - "; + if (gn->second.size () == 1) { + description += tl::to_string (tr ("Package %1").arg (tl::to_qstring (gn->second.front ()))); + } else { + description += tl::to_string (tr ("Packages %1").arg (tl::to_qstring (tl::join (gn->second, ",")))); + } + } + + external_paths.push_back (ExternalPathDescriptor (tl::to_string (macro_dir.path ()), description, macro_categories () [c].first, lay::MacroCollection::TechFolder, readonly_paths.find (t->first) != readonly_paths.end ())); } @@ -350,7 +369,7 @@ MacroController::sync_implicit_macros (bool ask_before_autorun) if (macro_dir.exists ()) { std::string description = tl::to_string (tr ("Package %1").arg (tl::to_qstring (g->name ()))); - external_paths.push_back (ExternalPathDescriptor (tl::to_string (macro_dir.path ()), description, macro_categories () [c].first, lay::MacroCollection::SaltFolder)); + external_paths.push_back (ExternalPathDescriptor (tl::to_string (macro_dir.path ()), description, macro_categories () [c].first, lay::MacroCollection::SaltFolder, g->is_readonly ())); } @@ -420,7 +439,7 @@ MacroController::sync_implicit_macros (bool ask_before_autorun) // In that case, the add_folder method will return 0. // TODO: is it wise to make this writeable? - lay::MacroCollection *mc = lay::MacroCollection::root ().add_folder (p->description, p->path, p->cat, false); + lay::MacroCollection *mc = lay::MacroCollection::root ().add_folder (p->description, p->path, p->cat, p->readonly); if (mc) { mc->set_virtual_mode (p->type); new_folders.push_back (mc); diff --git a/src/lay/layMacroController.h b/src/lay/layMacroController.h index 0eaf18d8d..e245bf643 100644 --- a/src/lay/layMacroController.h +++ b/src/lay/layMacroController.h @@ -180,8 +180,8 @@ private: */ struct ExternalPathDescriptor { - ExternalPathDescriptor (const std::string &_path, const std::string &_description, const std::string &_cat, lay::MacroCollection::FolderType _type) - : path (_path), description (_description), cat (_cat), type (_type) + ExternalPathDescriptor (const std::string &_path, const std::string &_description, const std::string &_cat, lay::MacroCollection::FolderType _type, bool _readonly) + : path (_path), description (_description), cat (_cat), type (_type), readonly (_readonly) { // .. nothing yet .. } @@ -190,6 +190,7 @@ private: std::string description; std::string cat; lay::MacroCollection::FolderType type; + bool readonly; }; /** diff --git a/src/lay/layTechSetupDialog.cc b/src/lay/layTechSetupDialog.cc index 405274266..edddde5df 100644 --- a/src/lay/layTechSetupDialog.cc +++ b/src/lay/layTechSetupDialog.cc @@ -49,6 +49,28 @@ namespace lay { +// ---------------------------------------------------------------- + +static std::string +title_for_technology (const lay::Technology *t) +{ + std::string d; + if (t->name ().empty ()) { + d = t->description (); + } else { + d += t->name (); + if (! t->grain_name ().empty ()) { + d += " "; + d += tl::to_string (QObject::tr ("[Package %1]").arg (tl::to_qstring (t->grain_name ()))); + } + if (! t->description ().empty ()) { + d += " - "; + d += t->description (); + } + } + return d; +} + // ---------------------------------------------------------------- // TechBaseEditorPage implementation @@ -843,15 +865,8 @@ TechSetupDialog::update_tech_tree () QFont f (tech_tree->font ()); f.setItalic (t->second->is_readonly ()); - std::string d; - d += t->first; - if (! d.empty () && ! t->second->description ().empty ()) { - d += " - "; - } - d += t->second->description (); - QTreeWidgetItem *ti = new QTreeWidgetItem (tech_tree); - ti->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (d))); + ti->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (title_for_technology (t->second)))); ti->setData (0, Qt::UserRole, QVariant (tl::to_qstring (t->first))); ti->setData (0, Qt::FontRole, QVariant (f)); if (! t->second->tech_file_path ().empty ()) { @@ -1059,13 +1074,7 @@ TechSetupDialog::commit_tech_component () QTreeWidgetItem *item = tech_tree->topLevelItem (i - 1); lay::Technology *t = m_technologies.technology_by_name (tl::to_string (item->data (0, Qt::UserRole).toString ())); - std::string d = t->name (); - if (! d.empty () && ! t->description ().empty ()) { - d += " - "; - } - d += t->description (); - - item->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (d))); + item->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (title_for_technology (t)))); } diff --git a/src/lay/layTechnologyController.cc b/src/lay/layTechnologyController.cc index 51f7228b6..1d0e1491d 100644 --- a/src/lay/layTechnologyController.cc +++ b/src/lay/layTechnologyController.cc @@ -495,12 +495,18 @@ TechnologyController::rescan (lay::Technologies &technologies) } std::vector paths = m_paths; + std::set readonly_paths; + std::map grain_names; // add the salt grains as potential sources for tech 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 ()); + grain_names.insert (std::make_pair ((*g)->path (), (*g)->name ())); + if ((*g)->is_readonly ()) { + readonly_paths.insert ((*g)->path ()); + } } } @@ -511,6 +517,14 @@ TechnologyController::rescan (lay::Technologies &technologies) continue; } + bool readonly = (readonly_paths.find (*p) != readonly_paths.end ()); + + std::string grain_name; + std::map::const_iterator gn = grain_names.find (*p); + if (gn != grain_names.end ()) { + grain_name = gn->second; + } + QStringList name_filters; name_filters << QString::fromUtf8 ("*.lyt"); @@ -534,7 +548,8 @@ TechnologyController::rescan (lay::Technologies &technologies) lay::Technology t; t.load (tl::to_string (*lf)); t.set_persisted (false); // don't save that one in the configuration - t.set_readonly (! QFileInfo (dir.filePath (*lf)).isWritable ()); + t.set_readonly (readonly || ! QFileInfo (dir.filePath (*lf)).isWritable ()); + t.set_grain_name (grain_name); technologies.add (new lay::Technology (t)); } catch (tl::Exception &ex) { diff --git a/src/laybasic/layTechnology.cc b/src/laybasic/layTechnology.cc index 09e596bdd..9e4c15bcb 100644 --- a/src/laybasic/layTechnology.cc +++ b/src/laybasic/layTechnology.cc @@ -252,7 +252,7 @@ Technology::~Technology () Technology::Technology (const Technology &d) : tl::Object (), - m_name (d.m_name), m_description (d.m_description), m_dbu (d.m_dbu), + m_name (d.m_name), m_description (d.m_description), m_grain_name (d.m_grain_name), m_dbu (d.m_dbu), m_explicit_base_path (d.m_explicit_base_path), m_default_base_path (d.m_default_base_path), m_load_layout_options (d.m_load_layout_options), m_save_layout_options (d.m_save_layout_options), @@ -270,6 +270,7 @@ Technology &Technology::operator= (const Technology &d) m_name = d.m_name; m_description = d.m_description; + m_grain_name = d.m_grain_name; m_dbu = d.m_dbu; m_default_base_path = d.m_default_base_path; m_explicit_base_path = d.m_explicit_base_path; diff --git a/src/laybasic/layTechnology.h b/src/laybasic/layTechnology.h index 50fc61c1e..ff28f3eaf 100644 --- a/src/laybasic/layTechnology.h +++ b/src/laybasic/layTechnology.h @@ -280,6 +280,24 @@ public: } } + /** + * @brief Sets the package source + * + * This attribute indicates that this technology was contributed by a package + */ + void set_grain_name (const std::string &g) + { + m_grain_name = g; + } + + /** + * @brief Gets the package source + */ + const std::string &grain_name () const + { + return m_grain_name; + } + /** * @brief Gets the base path * @@ -575,6 +593,7 @@ public: private: std::string m_name, m_description; + std::string m_grain_name; double m_dbu; std::string m_explicit_base_path, m_default_base_path; db::LoadLayoutOptions m_load_layout_options;