From cd353219ce12d37cb476110a43f670679759f452 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 Nov 2019 12:36:02 +0100 Subject: [PATCH] Implemented #382: text editor view for user props This view is an alternative view to the table and allows copy/paste and faster editing. --- src/klayout.pro | 3 +- src/lay/lay/lay.pro | 1 - src/lay/lay/layMacroEditorPage.cc | 9 +- src/laybasic/laybasic/SelectStippleForm.ui | 115 ++++--- src/laybasic/laybasic/UserPropertiesForm.ui | 299 ++++++++++-------- src/laybasic/laybasic/layDialogs.cc | 187 +++++++++-- src/laybasic/laybasic/layDialogs.h | 16 +- .../laybasic}/layGenericSyntaxHighlighter.cc | 0 .../laybasic}/layGenericSyntaxHighlighter.h | 21 +- src/laybasic/laybasic/laybasic.pro | 6 +- src/laybasic/laybasic/laybasicResources.qrc | 1 + src/laybasic/laybasic/syntax/ur_text.xml | 89 ++++++ 12 files changed, 508 insertions(+), 239 deletions(-) rename src/{lay/lay => laybasic/laybasic}/layGenericSyntaxHighlighter.cc (100%) rename src/{lay/lay => laybasic/laybasic}/layGenericSyntaxHighlighter.h (96%) create mode 100644 src/laybasic/laybasic/syntax/ur_text.xml diff --git a/src/klayout.pro b/src/klayout.pro index e230d5efb..0f96adf0a 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -102,5 +102,6 @@ plugins.depends += lib rdb db unit_tests.depends += plugins $$MAIN_DEPENDS RESOURCES += \ - plugins/tools/import/lay_plugin/layResources.qrc + plugins/tools/import/lay_plugin/layResources.qrc \ + laybasic/laybasic/layResources.qrc diff --git a/src/lay/lay/lay.pro b/src/lay/lay/lay.pro index ef029a550..875c5bf13 100644 --- a/src/lay/lay/lay.pro +++ b/src/lay/lay/lay.pro @@ -119,7 +119,6 @@ SOURCES = \ layClipDialog.cc \ layCrashMessage.cc \ layFillDialog.cc \ - layGenericSyntaxHighlighter.cc \ layGSIHelpProvider.cc \ layHelpDialog.cc \ layHelpProvider.cc \ diff --git a/src/lay/lay/layMacroEditorPage.cc b/src/lay/lay/layMacroEditorPage.cc index 6c720c3ec..8969b7652 100644 --- a/src/lay/lay/layMacroEditorPage.cc +++ b/src/lay/lay/layMacroEditorPage.cc @@ -113,7 +113,14 @@ MacroEditorHighlighters::highlighter_for_scheme (QObject *parent, const std::str if (! scheme.empty ()) { QResource res (tl::to_qstring (":/syntax/" + scheme + ".xml")); - QByteArray data = qUncompress (QByteArray ((const char *) res.data (), int (res.size ()))); + + 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 ()); + } + QBuffer input (&data); input.open (QIODevice::ReadOnly); lay::GenericSyntaxHighlighter *hl = new GenericSyntaxHighlighter (parent, input, attributes); diff --git a/src/laybasic/laybasic/SelectStippleForm.ui b/src/laybasic/laybasic/SelectStippleForm.ui index 565174904..40b6a314b 100644 --- a/src/laybasic/laybasic/SelectStippleForm.ui +++ b/src/laybasic/laybasic/SelectStippleForm.ui @@ -1,10 +1,8 @@ - - - - + + SelectStippleForm - - + + 0 0 @@ -12,86 +10,102 @@ 374 - + Select Stipple Pattern - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - - - 5 - 7 + + + 0 0 - + true - + false - + false - + false - + QAbstractItemView::SingleSelection - + 34 36 - + QListView::Static - + QListView::ListMode - - + + Qt::Horizontal - - + + QFrame::NoFrame - + QFrame::Raised - - + + + 6 + + 0 - - 6 + + 0 + + + 0 + + + 0 - + Qt::Horizontal - + QSizePolicy::Expanding - + 81 31 @@ -100,21 +114,21 @@ - - + + OK - + true - - + + Cancel - + true @@ -124,11 +138,8 @@ - - - - - + + ok_button @@ -136,11 +147,11 @@ SelectStippleForm accept() - + 182 334 - + 163 178 @@ -152,11 +163,11 @@ SelectStippleForm reject() - + 275 334 - + 163 178 diff --git a/src/laybasic/laybasic/UserPropertiesForm.ui b/src/laybasic/laybasic/UserPropertiesForm.ui index ed835f01a..13799f0bd 100644 --- a/src/laybasic/laybasic/UserPropertiesForm.ui +++ b/src/laybasic/laybasic/UserPropertiesForm.ui @@ -1,179 +1,198 @@ - + + UserPropertiesForm - - + + 0 0 424 - 305 + 428 - + User Properties - - + + 9 - - 0 + + 9 - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 332 - 16 - - - - - - - + + 9 + + + 9 + + + 6 + + + + User properties - - - + + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - false - - - true - - - - Key - - - - - Value - - - - - - - + + + QFrame::NoFrame - + QFrame::Raised - - + + 0 - + + 0 + + + 0 + + + 0 + + 6 - - - - Qt::Vertical - - - - 61 - 114 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 201 - - - - - - - - Edit - - - - - - - - - - :/add.png - - - - - - - - - - :/del.png - - - - - - - Qt::Vertical + + + + 0 - - QSizePolicy::Fixed - - - - 332 - 16 - - - + + + Table + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 201 + + + + + + + + + + + + :/add.png:/add.png + + + + + + + + + + + :/del.png:/del.png + + + + + + + Edit + + + + + + + Qt::Vertical + + + + 61 + 211 + + + + + + + + false + + + true + + + + Key + + + + + Value + + + + + + + + + Text Editor + + + + + + + + + <html>Use the Variant Notation for key and value (<a href="int:/about/variant_notation.xml">See here for details</a>)</html> + + + true + + + + + + - + - prop_list - add_pb - remove_pb - edit_pb buttonBox - + @@ -182,11 +201,11 @@ UserPropertiesForm accept() - + 211 282 - + 211 152 @@ -198,11 +217,11 @@ UserPropertiesForm reject() - + 211 282 - + 211 152 diff --git a/src/laybasic/laybasic/layDialogs.cc b/src/laybasic/laybasic/layDialogs.cc index 41ca22a0f..1ed76c56f 100644 --- a/src/laybasic/laybasic/layDialogs.cc +++ b/src/laybasic/laybasic/layDialogs.cc @@ -36,6 +36,7 @@ #include "layLayoutView.h" #include "layCellTreeModel.h" #include "layQtTools.h" +#include "layGenericSyntaxHighlighter.h" #include "ui_LayerSourceDialog.h" #include "ui_NewLayoutPropertiesDialog.h" @@ -55,6 +56,9 @@ #include "ui_UserPropertiesForm.h" #include "ui_UserPropertiesEditForm.h" +#include +#include + namespace lay { @@ -1012,17 +1016,38 @@ FlattenInstOptionsDialog::exec_dialog (int &levels, bool &prune) // UserPropertiesForm implementation UserPropertiesForm::UserPropertiesForm (QWidget *parent) - : QDialog (parent), m_editable (false) + : QDialog (parent), m_editable (false), mp_prep (0) { setObjectName (QString::fromUtf8 ("user_properties_form")); mp_ui = new Ui::UserPropertiesForm (); mp_ui->setupUi (this); + mp_ui->text_edit->setFont (QFont ("Monospace")); + mp_ui->text_edit->setAcceptRichText (false); + connect (mp_ui->add_pb, SIGNAL (clicked ()), this, SLOT (add ())); connect (mp_ui->remove_pb, SIGNAL (clicked ()), this, SLOT (remove ())); connect (mp_ui->edit_pb, SIGNAL (clicked ()), this, SLOT (edit ())); connect (mp_ui->prop_list, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), this, SLOT (dbl_clicked (QTreeWidgetItem *, int))); + connect (mp_ui->mode_tab, SIGNAL (currentChanged (int)), this, SLOT (tab_changed (int))); + + activate_help_links (mp_ui->help_label); + + QResource res (tl::to_qstring (":/syntax/ur_text.xml")); + QByteArray data ((const char *) res.data (), int (res.size ())); + if (res.isCompressed ()) { + data = qUncompress (data); + } + + QBuffer input (&data); + input.open (QIODevice::ReadOnly); + mp_hl_basic_attributes.reset (new GenericSyntaxHighlighterAttributes ()); + mp_hl_attributes.reset (new GenericSyntaxHighlighterAttributes (mp_hl_basic_attributes.get ())); + lay::GenericSyntaxHighlighter *hl = new GenericSyntaxHighlighter (mp_ui->text_edit, input, mp_hl_attributes.get ()); + input.close (); + + hl->setDocument (mp_ui->text_edit->document ()); } UserPropertiesForm::~UserPropertiesForm () @@ -1031,35 +1056,12 @@ UserPropertiesForm::~UserPropertiesForm () mp_ui = 0; } -bool -UserPropertiesForm::show (lay::LayoutView *view, unsigned int cv_index, db::properties_id_type &prop_id) +db::PropertiesRepository::properties_set +UserPropertiesForm::get_properties (int tab) { - bool ret = false; + db::PropertiesRepository::properties_set props; -BEGIN_PROTECTED - - const lay::CellView &cv = view->cellview (cv_index); - db::PropertiesRepository &prep = cv->layout ().properties_repository (); - - m_editable = cv->layout ().is_editable (); - if (m_editable) { - mp_ui->edit_frame->show (); - } else { - mp_ui->edit_frame->hide (); - } - - mp_ui->prop_list->clear (); - - const db::PropertiesRepository::properties_set &props = prep.properties (prop_id); - for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) { - QTreeWidgetItem *entry = new QTreeWidgetItem (mp_ui->prop_list); - entry->setText (0, tl::to_qstring (prep.prop_name (p->first).to_parsable_string ())); - entry->setText (1, tl::to_qstring (p->second.to_parsable_string ())); - } - - if (exec ()) { - - db::PropertiesRepository::properties_set props; + if (tab == 0) { QTreeWidgetItemIterator it (mp_ui->prop_list); while (*it) { @@ -1076,13 +1078,92 @@ BEGIN_PROTECTED kex.read (k); kex.expect_end (); - props.insert (std::make_pair (prep.prop_name_id (k), v)); + props.insert (std::make_pair (mp_prep->prop_name_id (k), v)); ++it; } - prop_id = prep.properties_id (props); + } else { + + std::string text = tl::to_string (mp_ui->text_edit->toPlainText ()); + std::vector lines = tl::split (text, "\n"); + + for (std::vector::const_iterator l = lines.begin (); l != lines.end (); ++l) { + + tl::Extractor ex (l->c_str ()); + if (ex.at_end ()) { + // empty line + } else { + + tl::Variant v, k; + ex.read (k); + ex.test (":"); + ex.read (v); + ex.expect_end (); + + props.insert (std::make_pair (mp_prep->prop_name_id (k), v)); + + } + + } + + } + + return props; +} + +void +UserPropertiesForm::set_properties (const db::PropertiesRepository::properties_set &props) +{ + mp_ui->prop_list->clear (); + + for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) { + QTreeWidgetItem *entry = new QTreeWidgetItem (mp_ui->prop_list); + entry->setText (0, tl::to_qstring (mp_prep->prop_name (p->first).to_parsable_string ())); + entry->setText (1, tl::to_qstring (p->second.to_parsable_string ())); + } + + std::string text; + for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) { + text += mp_prep->prop_name (p->first).to_parsable_string (); + text += ": "; + text += p->second.to_parsable_string (); + text += "\n"; + } + + mp_ui->text_edit->setPlainText (tl::to_qstring (text)); +} + +bool +UserPropertiesForm::show (lay::LayoutView *view, unsigned int cv_index, db::properties_id_type &prop_id) +{ + bool ret = false; + +BEGIN_PROTECTED + + const lay::CellView &cv = view->cellview (cv_index); + mp_prep = &cv->layout ().properties_repository (); + + m_editable = cv->layout ().is_editable (); + if (m_editable) { + mp_ui->edit_frame->show (); + } else { + mp_ui->edit_frame->hide (); + } + + mp_ui->text_edit->setReadOnly (! m_editable); + mp_ui->prop_list->clear (); + + const db::PropertiesRepository::properties_set &props = mp_prep->properties (prop_id); + set_properties (props); + + if (exec ()) { + + if (m_editable) { + db::PropertiesRepository::properties_set props = get_properties (mp_ui->mode_tab->currentIndex ()); + prop_id = mp_prep->properties_id (props); + } ret = true; @@ -1090,6 +1171,8 @@ BEGIN_PROTECTED ret = false; } + mp_prep = 0; + END_PROTECTED return ret; @@ -1144,6 +1227,50 @@ UserPropertiesForm::dbl_clicked (QTreeWidgetItem *, int) edit (); } +void +UserPropertiesForm::tab_changed (int tab_index) +{ + if (! m_editable) { + return; + } + +BEGIN_PROTECTED + + int prev_tab = tab_index == 0 ? 1 : 0; + + try { + + // sync content + set_properties (get_properties (prev_tab)); + + } catch (...) { + + mp_ui->mode_tab->blockSignals (true); + mp_ui->mode_tab->setCurrentIndex (prev_tab); + mp_ui->mode_tab->blockSignals (false); + + throw; + + } + +END_PROTECTED +} + +void +UserPropertiesForm::accept () +{ +BEGIN_PROTECTED + + // Test for errors + if (m_editable) { + get_properties (mp_ui->mode_tab->currentIndex ()); + } + + QDialog::accept (); + +END_PROTECTED +} + void UserPropertiesForm::edit () { diff --git a/src/laybasic/laybasic/layDialogs.h b/src/laybasic/laybasic/layDialogs.h index 04ad110b1..38eb222d2 100644 --- a/src/laybasic/laybasic/layDialogs.h +++ b/src/laybasic/laybasic/layDialogs.h @@ -27,9 +27,11 @@ #include "dbPoint.h" #include "dbVector.h" #include "dbTypes.h" +#include "dbPropertiesRepository.h" #include "laybasicCommon.h" #include +#include class QTreeWidgetItem; @@ -39,6 +41,11 @@ namespace db struct LayerProperties; } +namespace lay +{ + class GenericSyntaxHighlighterAttributes; +} + namespace Ui { class LayerSourceDialog; @@ -412,11 +419,17 @@ public slots: void remove (); void edit (); void dbl_clicked (QTreeWidgetItem *, int); + void tab_changed (int); private: - bool m_editable; + db::PropertiesRepository::properties_set get_properties (int tab); + void set_properties (const db::PropertiesRepository::properties_set &props); + void accept (); + bool m_editable; + db::PropertiesRepository *mp_prep; Ui::UserPropertiesForm *mp_ui; + std::auto_ptr mp_hl_attributes, mp_hl_basic_attributes; }; /** @@ -432,7 +445,6 @@ public: bool show (QString &key, QString &value); virtual void accept (); -private: Ui::UserPropertiesEditForm *mp_ui; }; diff --git a/src/lay/lay/layGenericSyntaxHighlighter.cc b/src/laybasic/laybasic/layGenericSyntaxHighlighter.cc similarity index 100% rename from src/lay/lay/layGenericSyntaxHighlighter.cc rename to src/laybasic/laybasic/layGenericSyntaxHighlighter.cc diff --git a/src/lay/lay/layGenericSyntaxHighlighter.h b/src/laybasic/laybasic/layGenericSyntaxHighlighter.h similarity index 96% rename from src/lay/lay/layGenericSyntaxHighlighter.h rename to src/laybasic/laybasic/layGenericSyntaxHighlighter.h index cd69579d8..881daeb67 100644 --- a/src/lay/lay/layGenericSyntaxHighlighter.h +++ b/src/laybasic/laybasic/layGenericSyntaxHighlighter.h @@ -25,6 +25,7 @@ #define HDR_layGenericSyntaxHighlighter #include "tlString.h" +#include "laybasicCommon.h" #include #include @@ -40,7 +41,7 @@ namespace lay /** * @brief Specifies one element in the text block's user data */ -struct SyntaxHighlighterElement +struct LAYBASIC_PUBLIC SyntaxHighlighterElement { public: /** @@ -61,7 +62,7 @@ public: * * The user data will contain useful data for bracket detection and other things */ -class SyntaxHighlighterUserData +class LAYBASIC_PUBLIC SyntaxHighlighterUserData : public QTextBlockUserData { public: @@ -92,7 +93,7 @@ public: * Rule implementations must implement this base class in order to plug into the * generic syntax highlighter framework. */ -class GenericSyntaxHighlighterRuleBase +class LAYBASIC_PUBLIC GenericSyntaxHighlighterRuleBase { public: /** @@ -131,7 +132,7 @@ public: /** * @brief A specialization of GenericSyntaxHighlighterRuleBase which looks for a choice of strings */ -class GenericSyntaxHighlighterRuleStringList +class LAYBASIC_PUBLIC GenericSyntaxHighlighterRuleStringList : public GenericSyntaxHighlighterRuleBase { public: @@ -152,7 +153,7 @@ private: * * This object will forward the match request to the actual implementation. */ -class GenericSyntaxHighlighterRule +class LAYBASIC_PUBLIC GenericSyntaxHighlighterRule { public: /** @@ -319,7 +320,7 @@ private: * Special context ID's are 0 (#stay), -n (#pop n times). * A context is associated with an attribute, which is given by an integer ID. */ -class GenericSyntaxHighlighterContext +class LAYBASIC_PUBLIC GenericSyntaxHighlighterContext { public: enum { @@ -478,7 +479,7 @@ private: /** * @brief A collection of (named) contexts */ -class GenericSyntaxHighlighterContexts +class LAYBASIC_PUBLIC GenericSyntaxHighlighterContexts { public: GenericSyntaxHighlighterContexts (); @@ -579,7 +580,7 @@ enum def_style { /** * @brief A collection of attributes */ -class GenericSyntaxHighlighterAttributes +class LAYBASIC_PUBLIC GenericSyntaxHighlighterAttributes { public: typedef std::map::const_iterator const_iterator; @@ -672,7 +673,7 @@ private: /** * @brief The parser's state */ -class GenericSyntaxHighlighterState +class LAYBASIC_PUBLIC GenericSyntaxHighlighterState { public: GenericSyntaxHighlighterState (const GenericSyntaxHighlighterContexts *contexts); @@ -710,7 +711,7 @@ private: /** * @brief A generic syntax highlighter using "Kate"'s syntax highlight scripts */ -class GenericSyntaxHighlighter +class LAYBASIC_PUBLIC GenericSyntaxHighlighter : public QSyntaxHighlighter { public: diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index d74ab99fa..92422593e 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -177,7 +177,8 @@ SOURCES = \ layNetlistCrossReferenceModel.cc \ layNetlistBrowserTreeModel.cc \ layLibrariesView.cc \ - layBookmarksView.cc + layBookmarksView.cc \ + layGenericSyntaxHighlighter.cc HEADERS = \ gtf.h \ @@ -275,7 +276,8 @@ HEADERS = \ layNetlistCrossReferenceModel.h \ layNetlistBrowserTreeModel.h \ layLibrariesView.h \ - layBookmarksView.h + layBookmarksView.h \ + layGenericSyntaxHighlighter.h INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC diff --git a/src/laybasic/laybasic/laybasicResources.qrc b/src/laybasic/laybasic/laybasicResources.qrc index a5ff51cce..86e08c975 100644 --- a/src/laybasic/laybasic/laybasicResources.qrc +++ b/src/laybasic/laybasic/laybasicResources.qrc @@ -44,5 +44,6 @@ images/icon_device_bjt_32.png images/icon_device_bjt_24.png images/icon_device_bjt_16.png + syntax/ur_text.xml diff --git a/src/laybasic/laybasic/syntax/ur_text.xml b/src/laybasic/laybasic/syntax/ur_text.xml new file mode 100644 index 000000000..5858a407f --- /dev/null +++ b/src/laybasic/laybasic/syntax/ur_text.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +