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;