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 +
layLogViewerDialog.h
+
+
+ + + + + + 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 + + + + + + +