From 747807224b3dce9360118d1bf72a461615a84b5c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 6 Oct 2021 23:17:45 +0200 Subject: [PATCH 1/7] 2.5d view enhancements * Fine-tuned 2.5d view's key events * better error message in case of z-stack/layers mismatch * Don't confine bounding box to actual layout - that can be confusing --- src/plugins/tools/view_25d/lay_plugin/layD25View.cc | 2 +- .../tools/view_25d/lay_plugin/layD25ViewWidget.cc | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc index 0055a43cf..603136699 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc @@ -203,7 +203,7 @@ D25View::activated () bool any = mp_ui->d25_view->attach_view (view ()); if (! any) { mp_ui->d25_view->attach_view (0); - throw tl::Exception (tl::to_string (tr ("No z data configured for the layers in the view.\nUse \"Tools/Manage Technologies\" to set up a z stack."))); + throw tl::Exception (tl::to_string (tr ("No z data configured for the layers in this view.\nUse \"Tools/Manage Technologies\" to set up a z stack or check if it applies to the layers here."))); } mp_ui->d25_view->reset (); diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc index f83b57214..3eb97dfee 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc @@ -311,13 +311,13 @@ D25ViewWidget::keyPressEvent (QKeyEvent *event) // Move "into" or "out" - double d = (event->key () == Qt::Key_Up ? 0.1 : -0.1); + double d = (event->key () == Qt::Key_Up ? 0.05 : -0.05); QMatrix4x4 t; t.rotate (cam_azimuth (), 0.0, 1.0, 0.0); QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ())); - set_displacement (displacement () + d * cd); + set_displacement (displacement () + d * cd / m_scale_factor); } @@ -327,7 +327,7 @@ D25ViewWidget::keyPressEvent (QKeyEvent *event) // Ctrl + left/right changes azimuths - double d = (event->key () == Qt::Key_Right ? 2 : -2); + double d = (event->key () == Qt::Key_Right ? 1 : -1); double a = cam_azimuth () + d; if (a < -180.0) { @@ -348,7 +348,7 @@ D25ViewWidget::keyPressEvent (QKeyEvent *event) t.rotate (cam_azimuth (), 0.0, 1.0, 0.0); QVector3D cd = t.inverted ().map (QVector3D (cam_dist (), 0, 0)); - set_displacement (displacement () + d * cd); + set_displacement (displacement () + d * cd / m_scale_factor); } @@ -634,11 +634,6 @@ D25ViewWidget::prepare_view () } - m_bbox &= cell_bbox; - if (m_bbox.empty ()) { - return false; - } - bool any = false; tl::AbsoluteProgress progress (tl::to_string (tr ("Rendering ..."))); From ec527367f24698a794985e6b923b60fbf1ae2b6e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 6 Oct 2021 23:26:12 +0200 Subject: [PATCH 2/7] 'tap' shows layer details like view name --- src/edt/edt/edtMainService.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index f778d6fe2..133b6f18a 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -2115,7 +2115,7 @@ MainService::cm_tap () QPoint mp = view ()->view_object_widget ()->mapToGlobal (view ()->view_object_widget ()->mouse_position ()); for (std::vector::const_iterator l = tapped_layers.begin (); l != tapped_layers.end (); ++l) { - QAction *a = menu->addAction (lay::LayerTreeModel::icon_for_layer (*l, view (), icon_size, icon_size, 0, true), tl::to_qstring ((*l)->source (true).to_string ())); + QAction *a = menu->addAction (lay::LayerTreeModel::icon_for_layer (*l, view (), icon_size, icon_size, 0, true), tl::to_qstring ((*l)->display_string (view (), true, true /*with source*/))); a->setData (int (l - tapped_layers.begin ())); } From 710d217b173624ee01bd66fcec7d3d98219bcd21 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 7 Oct 2021 22:17:03 +0200 Subject: [PATCH 3/7] strmxor: better command line doc, show file read timing like main app. --- src/buddies/src/bd/strmxor.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index 6741f773b..6072e1e73 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -180,7 +180,8 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) << tl::arg ("input_b", &infile_b, "The second input file (any format, may be gzip compressed)") << tl::arg ("?output", &output, "The output file to which the XOR differences are written", "This argument is optional. If not given, the exit status alone will indicate whether the layouts " - "are identical or not." + "are identical or not. The output is a layout file. The format of the file is derived " + "from the file name's suffix (.oas[.gz] for (gzipped) OASIS, .gds[.gz] for (gzipped) GDS2 etc.)." ) << tl::arg ("-ta|--top-a=name", &top_a, "Specifies the top cell for the first layout", "Use this option to take a specific cell as the top cell from the first layout. All " @@ -248,6 +249,8 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) db::Layout layout_b; { + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading file (A): ")) + infile_a); + db::LoadLayoutOptions load_options; generic_reader_options_a.configure (load_options); @@ -257,6 +260,8 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) } { + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading file (B): ")) + infile_b); + db::LoadLayoutOptions load_options; generic_reader_options_b.configure (load_options); From 4d64e95680c22f5d693eea8825ed03447b7e41b5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 18 Oct 2021 23:08:38 +0200 Subject: [PATCH 4/7] Shape objects from custom queries 'select' are translated into shape markers when exporting to RDB --- src/lay/lay/laySearchReplaceDialog.cc | 5 +-- src/rdb/rdb/rdbUtils.cc | 47 +++++++++++++++++++++++++++ src/rdb/rdb/rdbUtils.h | 12 +++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/lay/lay/laySearchReplaceDialog.cc b/src/lay/lay/laySearchReplaceDialog.cc index 4f8196e64..3c70640ba 100644 --- a/src/lay/lay/laySearchReplaceDialog.cc +++ b/src/lay/lay/laySearchReplaceDialog.cc @@ -38,6 +38,7 @@ #include "tlLog.h" #include "tlProgress.h" #include "tlTimer.h" +#include "rdbUtils.h" #include #include @@ -537,10 +538,10 @@ SearchReplaceResults::export_rdb (rdb::Database &rdb, double dbu) rdb::Item *item = rdb.create_item (cell->id (), cat->id ()); if (! v->is_list ()) { - item->add_value (std::string (v->to_string ())); + rdb::add_item_value (item, *v, dbu); } else { for (std::vector::const_iterator i = v->get_list ().begin (); i != v->get_list ().end (); ++i) { - item->add_value (std::string (i->to_string ())); + rdb::add_item_value (item, *i, dbu); } } diff --git a/src/rdb/rdb/rdbUtils.cc b/src/rdb/rdb/rdbUtils.cc index 336ed963e..c6940a56a 100644 --- a/src/rdb/rdb/rdbUtils.cc +++ b/src/rdb/rdb/rdbUtils.cc @@ -317,5 +317,52 @@ void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb: } } +void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu) +{ + if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (dbu > 0 && v.is_user ()) { + db::DPoint p = db::CplxTrans (dbu) * v.to_user (); + item->add_value (db::DEdge (p, p)); + } else if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (dbu > 0 && v.is_user ()) { + db::DPolygon p; + db::DSimplePolygon sp = db::CplxTrans (dbu) * v.to_user (); + p.assign_hull (sp.begin_hull (), sp.end_hull ()); + item->add_value (p); + } else if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (dbu > 0 && v.is_user ()) { + item->add_value (db::CplxTrans (dbu) * v.to_user ()); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else if (v.is_user ()) { + db::DPoint p = v.to_user (); + item->add_value (db::DEdge (p, p)); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else if (v.is_user ()) { + db::DPolygon p; + db::DSimplePolygon sp = v.to_user (); + p.assign_hull (sp.begin_hull (), sp.end_hull ()); + item->add_value (p); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else if (v.is_user ()) { + item->add_value (v.to_user ()); + } else { + item->add_value (std::string (v.to_string ())); + } +} + } diff --git a/src/rdb/rdb/rdbUtils.h b/src/rdb/rdb/rdbUtils.h index d89cd6c72..f6b579008 100644 --- a/src/rdb/rdb/rdbUtils.h +++ b/src/rdb/rdb/rdbUtils.h @@ -136,6 +136,18 @@ RDB_PUBLIC_TEMPLATE void create_items_from_sequence (rdb::Database *db, rdb::id_ } } +/** + * @brief Creates a value from a tl::Variant + * + * This produces values which reflect some values the variant can assume - specifically + * shapes are converted into corresponding RDB values. The database unit is used to + * translate integer-type values. Using a database unit of 0 will disable the conversion of + * such types. + * + * Unknown types are converted to strings. + */ +RDB_PUBLIC void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu = 0.0); + } #endif From 04deb785baa35b2b7790a68fc3a3749edbb3e7b4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 18 Oct 2021 23:10:39 +0200 Subject: [PATCH 5/7] Asking whether to apply a .lyp file on multiple layouts on MRU-listed .lyp files too. --- src/lay/lay/layMainWindow.cc | 67 +++++++++++++++++++----------------- src/lay/lay/layMainWindow.h | 1 + 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index c97f0def7..b886acfc8 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2025,44 +2025,47 @@ MainWindow::cm_load_layer_props () if (current_view ()) { std::string fn; if (mp_lprops_fdia->get_open (fn, tl::to_string (QObject::tr ("Load Layer Properties File")))) { - - int target_cv_index = -2; - - if (current_view ()->cellviews () > 1 && is_single_cv_layer_properties_file (fn)) { - - QStringList items; - items << QString (QObject::tr ("Take it as it is")); - items << QString (QObject::tr ("Apply to all layouts")); - for (unsigned int i = 0; i < current_view ()->cellviews (); ++i) { - items << QString (tl::to_qstring (tl::to_string (QObject::tr ("Apply to ")) + current_view ()->cellview (i)->name () + " (@" + tl::to_string (i + 1) + ")")); - } - - bool ok; - QString item = QInputDialog::getItem(this, QObject::tr ("Apply Layer Properties File"), - QObject::tr ("There are multiple layouts in that panel but the layer properties file contains properties for a single one.\nWhat should be done?"), - items, 1, false, &ok); - if (!ok || item.isEmpty()) { - return; - } - - target_cv_index = items.indexOf (item) - 2; - - } - - if (target_cv_index > -2) { - load_layer_properties (fn, target_cv_index, false /*current view only*/, false /*don't add default*/); - } else { - load_layer_properties (fn, false /*current view only*/, false /*don't add default*/); - } - + load_layer_props_from_file (fn); add_to_other_mru (fn, cfg_mru_layer_properties); - } } else { throw tl::Exception (tl::to_string (QObject::tr ("No view open to load the layer properties for"))); } } +void +MainWindow::load_layer_props_from_file (const std::string &fn) +{ + int target_cv_index = -2; + + if (current_view ()->cellviews () > 1 && is_single_cv_layer_properties_file (fn)) { + + QStringList items; + items << QString (QObject::tr ("Take it as it is")); + items << QString (QObject::tr ("Apply to all layouts")); + for (unsigned int i = 0; i < current_view ()->cellviews (); ++i) { + items << QString (tl::to_qstring (tl::to_string (QObject::tr ("Apply to ")) + current_view ()->cellview (i)->name () + " (@" + tl::to_string (i + 1) + ")")); + } + + bool ok; + QString item = QInputDialog::getItem(this, QObject::tr ("Apply Layer Properties File"), + QObject::tr ("There are multiple layouts in that panel but the layer properties file contains properties for a single one.\nWhat should be done?"), + items, 1, false, &ok); + if (!ok || item.isEmpty()) { + return; + } + + target_cv_index = items.indexOf (item) - 2; + + } + + if (target_cv_index > -2) { + load_layer_properties (fn, target_cv_index, false /*current view only*/, false /*don't add default*/); + } else { + load_layer_properties (fn, false /*current view only*/, false /*don't add default*/); + } +} + void MainWindow::save_session (const std::string &fn) { @@ -3238,7 +3241,7 @@ MainWindow::open_recent_layer_properties (size_t n) if (n < m_mru_layer_properties.size ()) { std::string fn = m_mru_layer_properties [n]; - load_layer_properties (fn, false /*current view only*/, false /*don't add default*/); + load_layer_props_from_file (fn); add_to_other_mru (fn, cfg_mru_layer_properties); // make it the latest } diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index f9fe51611..cb2f2246d 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -805,6 +805,7 @@ private: int dirty_files (std::string &dirty_files); + void load_layer_props_from_file (const std::string &fn); void interactive_close_view (int index, bool all_cellviews); void call_on_current_view (void (lay::LayoutView::*func) (), const std::string &op_desc); void current_view_changed (); From 97d393c78a8e63c4074d9089b0b2b64fb5089206 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 18 Oct 2021 23:24:28 +0200 Subject: [PATCH 6/7] Layout#is_editable --- src/laybasic/laybasic/gsiDeclLayLayoutView.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc index a01db5183..938ca9d36 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc @@ -690,6 +690,11 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou "\n" "In 0.25, this method has been moved from MainWindow to LayoutView.\n" ) + + gsi::method ("is_editable?", &lay::LayoutView::is_editable, + "@brief Returns true if the view is in editable mode\n" + "\n" + "This read-only attribute has been added in version 0.27.5.\n" + ) + gsi::method ("reload_layout", &lay::LayoutView::reload_layout, gsi::arg ("cv"), "@brief Reloads the given cellview\n" "\n" From 89a50abeddf99f26c1a7b4cc74f8081d1e9bec2d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 19 Oct 2021 00:11:27 +0200 Subject: [PATCH 7/7] Some more documentation about layer views. --- src/lay/lay/doc/manual/basic.xml | 2 +- .../lay/doc/manual/layer_source_expert.xml | 4 + src/lay/lay/doc/manual/layer_views.xml | 84 +++++++++++++++++++ src/lay/lay/layHelpResources.qrc | 1 + 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/lay/lay/doc/manual/layer_views.xml diff --git a/src/lay/lay/doc/manual/basic.xml b/src/lay/lay/doc/manual/basic.xml index 92969e177..ec136b253 100644 --- a/src/lay/lay/doc/manual/basic.xml +++ b/src/lay/lay/doc/manual/basic.xml @@ -24,9 +24,9 @@ + - diff --git a/src/lay/lay/doc/manual/layer_source_expert.xml b/src/lay/lay/doc/manual/layer_source_expert.xml index 30619a4c1..97a50d9dc 100644 --- a/src/lay/lay/doc/manual/layer_source_expert.xml +++ b/src/lay/lay/doc/manual/layer_source_expert.xml @@ -100,5 +100,9 @@ a selector as well, only those shapes will be shown that meet both criteria.

+

+ A general description for the source notation is found here: . +

+ diff --git a/src/lay/lay/doc/manual/layer_views.xml b/src/lay/lay/doc/manual/layer_views.xml new file mode 100644 index 000000000..c9c294b0c --- /dev/null +++ b/src/lay/lay/doc/manual/layer_views.xml @@ -0,0 +1,84 @@ + + + + + + The Layer List (Layer Views) + + + +

+ An important concept in KLayout are the layer views. KLayout displays the layers + of a layout by default in a list on the right side of the main window. + This list however, does not directly reflect the layers in the layout database. + Instead this list is a collection of "views". A view is a description of what is + to be displayed and how. +

+ +

+ Essentially, the entries in the layer list are pointers to layers in the + database, together with a description how to paint the shapes on these layers (the + "layer properties"). +

+ +

+ The pointer is the "source" of a layer view. This is typically a GDS layer and datatype, + but can be a layer name (for DXF for example). There are also abstract sources (such as + cell boundaries) and the sources can include selectors or modifiers. Selectors are + used to only display shapes with certain user properties or from certain hierarchy + levels. Modifiers transform the shapes before they are drawn for example. + The source is defined by a "source specification" - this is a string describing the + database layer and selectors and modifiers. A simple source string is "1/0" which is + for GDS layer 1, datatype 0 without and selectors or modifiers. + To change the source, use "Change Source" from the layer list's context menu. +

+ +

+ See for some source specification string applications + and more details. +

+ +

+ Beside the source, a layer entry has a display name. This is an arbitrary text + providing a description for the user. By default - when no such name is present - + the source of the layer will be displayed. + To change the display name, use "Rename" from the layer list's context menu. +

+ +

+ Plus of course, the layer views have many options to specify the drawing style, + animations and decorations. +

+ +

+ The concept of separating views from the database layers opens some interesting options: +

+ +
    +
  • Layer views can refer to individual layouts from multi-layout views (through the "@1", "@2", ... notation in the source). + Hence, multiple layouts can be mixed in a single layer list.
  • +
  • Layers can be present in the list which do not need to be present in the database. Such a layer is shown as empty. + This is important as in GDS an empty layer is equivalent to non-existing. Still you may want to have it shown in the + layer list - the views offer this option.
  • +
  • Vice versa, database layer may not be listed in the layer list if no corresponding layer view is present. This + way, auxiliary or debug layers can be omitted from the layer list. A "wildcard specification" is available to make + sure, all layers are shown if you need to see all.
  • +
  • Multiple tabs can be present to provide multiple views on the same layouts. This is just an alternative set of + layer views.
  • +
  • Layer grouping, sorting etc. are just operations on the views, no database change is involved.
  • +
+ +

+ The concept on the other hand is slightly counter-intuitive at first. + Here are some hints: +

+ +
    +
  • Renaming a layer does not change the source - if you rename a layer to something like "1/0", you are likely to fool yourself thinking this is layer 1, datatype 0.
  • +
  • Changing a layer view's source does not change the database too - it will just change the pointer. To change a layer's information in the database, use Edit/Layer/Edit Layer Specification.
  • +
  • Deleting a layer from the layer list does not delete the layer from the database. Use Edit/Layer/Delete Layer instead.
  • +
  • Additing a new layer does not immediately create the layer in the database. Only once you draw something on that layer, it is generated in the database.
  • +
+ +
+ diff --git a/src/lay/lay/layHelpResources.qrc b/src/lay/lay/layHelpResources.qrc index 0e0053df0..06524e1f5 100644 --- a/src/lay/lay/layHelpResources.qrc +++ b/src/lay/lay/layHelpResources.qrc @@ -158,6 +158,7 @@ doc/manual/landmarks.xml doc/manual/layer_animation.xml doc/manual/layer_boolean.xml + doc/manual/layer_views.xml doc/manual/layer_color.xml doc/manual/layer_content.xml doc/manual/layer_fill.xml