diff --git a/src/lay/SaltGrainTemplateSelectionDialog.ui b/src/lay/SaltGrainTemplateSelectionDialog.ui
new file mode 100644
index 000000000..65406eb88
--- /dev/null
+++ b/src/lay/SaltGrainTemplateSelectionDialog.ui
@@ -0,0 +1,237 @@
+
+
+ SaltGrainTemplateSelectionDialog
+
+
+
+ 0
+ 0
+ 401
+ 499
+
+
+
+ Create Package
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Template
+
+
+
+ -
+
+
+ true
+
+
+
+ 64
+ 64
+
+
+
+ false
+
+
+
+ -
+
+
+
+ true
+
+
+
+ (Pick a template with which to initialize your new package)
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 10
+
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Package Name
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ -
+
+
+ Qt::NoFocus
+
+
+ ...
+
+
+
+ :/warn.png:/warn.png
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+ 50
+ true
+ false
+
+
+
+ (Choose a simple name composed of letters, digits and underscores. Use the notation "group/package" to create a package inside a group)
+
+
+ true
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+ :/add.png:/add.png
+
+
+ New
+
+
+ New package
+
+
+
+
+
+ :/clear.png:/clear.png
+
+
+ Delete
+
+
+ Delete package
+
+
+
+
+
+ :/import.png:/import.png
+
+
+ Import
+
+
+ Import package
+
+
+
+
+
+ lay::AlertLogButton
+ QToolButton
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ SaltGrainTemplateSelectionDialog
+ accept()
+
+
+ 273
+ 431
+
+
+ 276
+ 448
+
+
+
+
+ buttonBox
+ rejected()
+ SaltGrainTemplateSelectionDialog
+ reject()
+
+
+ 351
+ 426
+
+
+ 363
+ 445
+
+
+
+
+
diff --git a/src/lay/lay.pro b/src/lay/lay.pro
index 4c4c804f7..7b684827e 100644
--- a/src/lay/lay.pro
+++ b/src/lay/lay.pro
@@ -99,7 +99,8 @@ FORMS = \
TechSaveOptionsEditorPage.ui \
MainConfigPage7.ui \
SaltManagerDialog.ui \
- SaltGrainPropertiesDialog.ui
+ SaltGrainPropertiesDialog.ui \
+ SaltGrainTemplateSelectionDialog.ui
SOURCES = \
gsiDeclLayApplication.cc \
@@ -156,6 +157,7 @@ RESOURCES = layBuildInMacros.qrc \
layLayoutStatistics.qrc \
layMacroTemplates.qrc \
layResources.qrc \
+ laySaltTemplates.qrc
INCLUDEPATH += ../tl ../gsi ../db ../rdb ../laybasic ../ant ../img ../edt
DEPENDPATH += ../tl ../gsi ../db ../rdb ../laybasic ../ant ../img ../edt
diff --git a/src/lay/laySalt.cc b/src/lay/laySalt.cc
index 156cf0ec3..6e3ba10cb 100644
--- a/src/lay/laySalt.cc
+++ b/src/lay/laySalt.cc
@@ -81,11 +81,15 @@ Salt::grain_by_name (const std::string &name)
void
Salt::add_location (const std::string &path)
{
- // do nothing if the collection is already there
- QFileInfo fi (tl::to_qstring (path));
- for (lay::SaltGrains::collection_iterator g = m_root.begin_collections (); g != m_root.end_collections (); ++g) {
- if (QFileInfo (tl::to_qstring (g->path ())) == fi) {
- return;
+ tl_assert (! path.empty ());
+
+ if (path[0] != ':') {
+ // do nothing if the collection is already there
+ QFileInfo fi (tl::to_qstring (path));
+ for (lay::SaltGrains::collection_iterator g = m_root.begin_collections (); g != m_root.end_collections (); ++g) {
+ if (QFileInfo (tl::to_qstring (g->path ())) == fi) {
+ return;
+ }
}
}
diff --git a/src/lay/laySaltGrain.cc b/src/lay/laySaltGrain.cc
index 49152e4ae..af3f39130 100644
--- a/src/lay/laySaltGrain.cc
+++ b/src/lay/laySaltGrain.cc
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
namespace lay
{
@@ -326,8 +327,28 @@ SaltGrain::is_readonly () const
void
SaltGrain::load (const std::string &p)
{
- tl::XMLFileSource source (p);
- xml_struct.parse (source, *this);
+ tl_assert (!p.empty ());
+
+ if (p[0] != ':') {
+
+ tl::XMLFileSource source (p);
+ xml_struct.parse (source, *this);
+
+ } else {
+
+ QResource res (tl::to_qstring (p));
+ QByteArray data;
+ if (res.isCompressed ()) {
+ data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
+ } else {
+ data = QByteArray ((const char *)res.data (), (int)res.size ());
+ }
+
+ std::string str_data (data.constData (), data.size ());
+ tl::XMLStringSource source (str_data);
+ xml_struct.parse (source, *this);
+
+ }
}
void
@@ -376,9 +397,15 @@ SaltGrain::from_url (const std::string &url)
bool
SaltGrain::is_grain (const std::string &path)
{
- QDir dir (tl::to_qstring (path));
- QString gf = dir.filePath (tl::to_qstring (grain_filename));
- return QFileInfo (gf).exists ();
+ tl_assert (! path.empty ());
+
+ if (path[0] != ':') {
+ QDir dir (tl::to_qstring (path));
+ QString gf = dir.filePath (tl::to_qstring (grain_filename));
+ return QFileInfo (gf).exists ();
+ } else {
+ return QResource (tl::to_qstring (path + "/" + grain_filename)).isValid ();
+ }
}
}
diff --git a/src/lay/laySaltGrains.cc b/src/lay/laySaltGrains.cc
index 9c17944c6..5c80cc884 100644
--- a/src/lay/laySaltGrains.cc
+++ b/src/lay/laySaltGrains.cc
@@ -26,6 +26,7 @@
#include
#include
+#include
namespace lay
{
@@ -129,37 +130,102 @@ SaltGrains::is_readonly () const
return QFileInfo (tl::to_qstring (path ())).isWritable ();
}
+namespace
+{
+
+/**
+ * @brief A helper class required because directory traversal is not supported by QResource directly
+ */
+class OpenResource
+ : public QResource
+{
+public:
+ using QResource::isDir;
+ using QResource::isFile;
+ using QResource::children;
+
+ OpenResource (const QString &path)
+ : QResource (path)
+ {
+ // .. nothing yet ..
+ }
+};
+
+}
+
SaltGrains
SaltGrains::from_path (const std::string &path, const std::string &prefix)
{
+ tl_assert (! path.empty ());
+
SaltGrains grains;
grains.set_path (path);
- QDir dir (tl::to_qstring (path));
- QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Dirs, QDir::Name);
- for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) {
+ if (path[0] != ':') {
+
+ QDir dir (tl::to_qstring (path));
+ QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Dirs, QDir::Name);
+ for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) {
+
+ std::string new_prefix = prefix;
+ if (! new_prefix.empty ()) {
+ new_prefix += "/";
+ }
+ new_prefix += tl::to_string (*e);
+
+ std::string epath = tl::to_string (dir.absoluteFilePath (*e));
+ if (SaltGrain::is_grain (epath)) {
+ try {
+ SaltGrain g (SaltGrain::from_path (epath));
+ g.set_name (new_prefix);
+ grains.add_grain (g);
+ } catch (...) {
+ // ignore errors (TODO: what to do here?)
+ }
+ } else if (QFileInfo (tl::to_qstring (epath)).isDir ()) {
+ SaltGrains c = SaltGrains::from_path (epath, new_prefix);
+ c.set_name (new_prefix);
+ if (! c.is_empty ()) {
+ grains.add_collection (c);
+ }
+ }
- std::string new_prefix = prefix;
- if (! new_prefix.empty ()) {
- new_prefix += "/";
}
- new_prefix += tl::to_string (*e);
- std::string epath = tl::to_string (dir.absoluteFilePath (*e));
- if (SaltGrain::is_grain (epath)) {
- try {
- SaltGrain g (SaltGrain::from_path (epath));
- g.set_name (new_prefix);
- grains.add_grain (g);
- } catch (...) {
- // ignore errors (TODO: what to do here?)
- }
- } else if (QFileInfo (tl::to_qstring (epath)).isDir ()) {
- SaltGrains c = SaltGrains::from_path (epath, new_prefix);
- c.set_name (new_prefix);
- if (! c.is_empty ()) {
- grains.add_collection (c);
+ } else {
+
+ OpenResource resource (tl::to_qstring (path));
+ if (resource.isDir ()) {
+
+ QStringList templ_dir = resource.children ();
+ for (QStringList::const_iterator t = templ_dir.begin (); t != templ_dir.end (); ++t) {
+
+ std::string new_prefix = prefix;
+ if (! new_prefix.empty ()) {
+ new_prefix += "/";
+ }
+ new_prefix += tl::to_string (*t);
+
+ std::string epath = path + "/" + tl::to_string (*t);
+
+ if (SaltGrain::is_grain (epath)) {
+ try {
+ SaltGrain g (SaltGrain::from_path (epath));
+ g.set_name (new_prefix);
+ grains.add_grain (g);
+ } catch (...) {
+ // ignore errors (TODO: what to do here?)
+ }
+ } else if (OpenResource (tl::to_qstring (epath)).isDir ()) {
+ SaltGrains c = SaltGrains::from_path (epath, new_prefix);
+ c.set_name (new_prefix);
+ if (! c.is_empty ()) {
+ grains.add_collection (c);
+ }
+ }
+
}
+
}
}
diff --git a/src/lay/laySaltManagerDialog.cc b/src/lay/laySaltManagerDialog.cc
index 7730310bc..71a34dba3 100644
--- a/src/lay/laySaltManagerDialog.cc
+++ b/src/lay/laySaltManagerDialog.cc
@@ -23,6 +23,7 @@
#include "laySaltManagerDialog.h"
#include "laySaltGrainPropertiesDialog.h"
#include "laySalt.h"
+#include "ui_SaltGrainTemplateSelectionDialog.h"
#include "tlString.h"
#include
@@ -33,6 +34,7 @@
#include
#include
#include
+#include
namespace lay
{
@@ -219,6 +221,56 @@ public:
}
};
+// --------------------------------------------------------------------------------------
+
+/**
+ * @brief A tiny dialog to select a template and a name for the grain
+ */
+class SaltGrainTemplateSelectionDialog
+ : public QDialog, private Ui::SaltGrainTemplateSelectionDialog
+{
+public:
+ SaltGrainTemplateSelectionDialog (QWidget *parent)
+ : QDialog (parent)
+ {
+ Ui::SaltGrainTemplateSelectionDialog::setupUi (this);
+
+ m_salt_templates.add_location (":/salt_templates");
+ salt_view->setModel (new SaltModel (this, &m_salt_templates));
+ salt_view->setItemDelegate (new SaltItemDelegate (this));
+ salt_view->setCurrentIndex (salt_view->model ()->index (0, 0, QModelIndex ()));
+ }
+
+ lay::SaltGrain templ () const
+ {
+ SaltModel *model = dynamic_cast (salt_view->model ());
+ tl_assert (model != 0);
+
+ SaltGrain *g = model->grain_from_index (salt_view->currentIndex ());
+ tl_assert (g != 0);
+
+ g->set_name (tl::to_string (name_edit->text ().simplified ()));
+
+ return *g;
+ }
+
+ void accept ()
+ {
+ name_alert->clear ();
+ std::string name = tl::to_string (name_edit->text ().simplified ());
+ if (name.empty ()) {
+ name_alert->error () << tr ("Name must not be empty");
+ } else if (! SaltGrain::valid_name (name)) {
+ name_alert->error () << tr ("Name is not valid (must be composed of letters, digits or underscores.\nGroups and names need to be separated with slashes.");
+ } else {
+ QDialog::accept ();
+ }
+ }
+
+private:
+ lay::Salt m_salt_templates;
+};
+
// --------------------------------------------------------------------------------------
// SaltManager implementation
@@ -242,6 +294,9 @@ SaltManagerDialog::SaltManagerDialog (QWidget *parent)
mp_properties_dialog = new lay::SaltGrainPropertiesDialog (this);
connect (edit_button, SIGNAL (clicked ()), this, SLOT (edit_properties ()));
+ connect (create_button, SIGNAL (clicked ()), this, SLOT (create_grain ()));
+ connect (delete_button, SIGNAL (clicked ()), this, SLOT (delete_grain ()));
+ connect (install_button, SIGNAL (clicked ()), this, SLOT (install_grain ()));
// @@@
salt = lay::Salt (); salt_initialized = false;
@@ -279,6 +334,58 @@ SaltManagerDialog::edit_properties ()
}
}
+// @@@
+namespace
+{
+
+/**
+ * @brief A helper class required because directory traversal is not supported by QResource directly
+ */
+class OpenResource
+ : public QResource
+{
+public:
+ using QResource::isDir;
+ using QResource::isFile;
+ using QResource::children;
+
+ OpenResource (const QString &path)
+ : QResource (path)
+ {
+ // .. nothing yet ..
+ }
+};
+
+}
+// @@@
+
+void
+SaltManagerDialog::create_grain ()
+{
+ SaltGrainTemplateSelectionDialog temp_dialog (this);
+ if (temp_dialog.exec ()) {
+
+ // @@@
+
+ }
+}
+
+void
+SaltManagerDialog::delete_grain ()
+{
+
+ // @@@
+
+}
+
+void
+SaltManagerDialog::install_grain ()
+{
+
+ // @@@
+
+}
+
void
SaltManagerDialog::salt_changed ()
{
diff --git a/src/lay/laySaltManagerDialog.h b/src/lay/laySaltManagerDialog.h
index 170e02b7d..232d40403 100644
--- a/src/lay/laySaltManagerDialog.h
+++ b/src/lay/laySaltManagerDialog.h
@@ -64,6 +64,21 @@ private slots:
*/
void edit_properties ();
+ /**
+ * @brief Called when the "edit" button is pressed
+ */
+ void create_grain ();
+
+ /**
+ * @brief Called when the "delete" button is pressed
+ */
+ void delete_grain ();
+
+ /**
+ * @brief Called when the "install" button is pressed
+ */
+ void install_grain ();
+
private:
lay::Salt *mp_salt;
bool m_current_changed_enabled;
diff --git a/src/lay/laySaltTemplates.qrc b/src/lay/laySaltTemplates.qrc
new file mode 100644
index 000000000..e4155fe58
--- /dev/null
+++ b/src/lay/laySaltTemplates.qrc
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+ salt_templates/font/grain.xml
+
+
+
+
+
+
+ salt_templates/lib/grain.xml
+
+
+
+
+
+
+ salt_templates/pcell_lib/grain.xml
+
+
+
+
+
+
+ salt_templates/macro/grain.xml
+
+
+
+
+
+
+ salt_templates/pymacro/grain.xml
+
+
+
+
+
+
+ salt_templates/tech/grain.xml
+
+
+
+
+
diff --git a/src/lay/salt_templates/font/grain.xml b/src/lay/salt_templates/font/grain.xml
new file mode 100644
index 000000000..593a48147
--- /dev/null
+++ b/src/lay/salt_templates/font/grain.xml
@@ -0,0 +1,16 @@
+
+
+ font
+ 0.0
+ Font package
+ This template provides a font for the Basic.TEXT PCell
+
+
+ GPLv3
+
+
+
+
+
+
+
diff --git a/src/lay/salt_templates/lib/grain.xml b/src/lay/salt_templates/lib/grain.xml
new file mode 100644
index 000000000..a071c2676
--- /dev/null
+++ b/src/lay/salt_templates/lib/grain.xml
@@ -0,0 +1,16 @@
+
+
+ lib
+ 0.0
+ Static Library
+ This template provides a static library
+
+
+ GPLv3
+
+
+
+
+
+
+
diff --git a/src/lay/salt_templates/macro/grain.xml b/src/lay/salt_templates/macro/grain.xml
new file mode 100644
index 000000000..ae9c5ffe2
--- /dev/null
+++ b/src/lay/salt_templates/macro/grain.xml
@@ -0,0 +1,16 @@
+
+
+ macro
+ 0.0
+ Ruby Macro
+ This template provides a Ruby macro
+
+
+ GPLv3
+
+
+
+
+
+
+
diff --git a/src/lay/salt_templates/pcell_lib/grain.xml b/src/lay/salt_templates/pcell_lib/grain.xml
new file mode 100644
index 000000000..20a656273
--- /dev/null
+++ b/src/lay/salt_templates/pcell_lib/grain.xml
@@ -0,0 +1,16 @@
+
+
+ macro
+ 0.0
+ PCell library
+ This template provides a PCell library implemented in Ruby
+
+
+ GPLv3
+
+
+
+
+
+
+
diff --git a/src/lay/salt_templates/pymacro/grain.xml b/src/lay/salt_templates/pymacro/grain.xml
new file mode 100644
index 000000000..2b281fcc9
--- /dev/null
+++ b/src/lay/salt_templates/pymacro/grain.xml
@@ -0,0 +1,16 @@
+
+
+ macro
+ 0.0
+ Python Macro
+ This template provides a Python macro
+
+
+ GPLv3
+
+
+
+
+
+
+
diff --git a/src/lay/salt_templates/tech/grain.xml b/src/lay/salt_templates/tech/grain.xml
new file mode 100644
index 000000000..2def15e72
--- /dev/null
+++ b/src/lay/salt_templates/tech/grain.xml
@@ -0,0 +1,16 @@
+
+
+ macro
+ 0.0
+ Technology
+ This template provides a technology
+
+
+ GPLv3
+
+
+
+
+
+
+