From 3bc14e1e79d2d9bfdbe0354e8b9ab88e71669e5c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Apr 2023 14:47:52 +0200 Subject: [PATCH 1/7] Fixed issue-1345 (feature request: create a def single/mulitpart path import option) The option is called "--lefdef-joined-paths" for strm* buddy tools and "joined_paths" for pya/RBA. Wires with multiple segments are combined into long paths when possible - this fails on anisotropic widths and 45 degree segments. --- src/buddies/src/bd/bdReaderOptions.cc | 7 + src/buddies/src/bd/bdReaderOptions.h | 1 + .../lefdef/db_plugin/dbDEFImporter.cc | 26 ++-- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 2 + .../lefdef/db_plugin/dbLEFDEFImporter.h | 11 ++ .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 1 + .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 14 ++ .../LEFDEFTechnologyComponentEditor.ui | 131 ++++++++++-------- .../lay_plugin/layLEFDEFImportDialogs.cc | 2 + .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 10 ++ testdata/lefdef/issue-1345/au-nojoin.oas.gz | Bin 0 -> 545 bytes testdata/lefdef/issue-1345/au.oas.gz | Bin 0 -> 543 bytes testdata/lefdef/issue-1345/in.def | 16 +++ testdata/lefdef/issue-1345/in.lef | 40 ++++++ 14 files changed, 189 insertions(+), 72 deletions(-) create mode 100644 testdata/lefdef/issue-1345/au-nojoin.oas.gz create mode 100644 testdata/lefdef/issue-1345/au.oas.gz create mode 100644 testdata/lefdef/issue-1345/in.def create mode 100644 testdata/lefdef/issue-1345/in.lef diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc index e10ab80dc..3d3b9f75e 100644 --- a/src/buddies/src/bd/bdReaderOptions.cc +++ b/src/buddies/src/bd/bdReaderOptions.cc @@ -118,6 +118,7 @@ GenericReaderOptions::GenericReaderOptions () m_lefdef_read_lef_with_def = load_options.get_option_by_name ("lefdef_config.read_lef_with_def").to_bool (); m_lefdef_separate_groups = load_options.get_option_by_name ("lefdef_config.separate_groups").to_bool (); + m_lefdef_joined_paths = load_options.get_option_by_name ("lefdef_config.joined_paths").to_bool (); m_lefdef_map_file = load_options.get_option_by_name ("lefdef_config.map_file").to_string (); m_lefdef_macro_resolution_mode = load_options.get_option_by_name ("lefdef_config.macro_resolution_mode").to_int (); } @@ -441,6 +442,11 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd) "This option is used together with '--" + m_long_prefix + "lefdef-produce-regions'. If given, the region polygons will be put " "into a cell hierarchy where the cells indicate the region groups.\n" ) + << tl::arg (group + + "#--" + m_long_prefix + "lefdef-joined-paths", &m_lefdef_joined_paths, "Specifies to produce joined paths for wires", + "If given, multi-segment paths are created for wires if possible (this will fail for 45 degree segments for example). " + "By default, individual straight segments will be produced." + ) << tl::arg (group + "#!--" + m_long_prefix + "lefdef-dont-produce-via-geometry", &m_lefdef_produce_via_geometry, "Skips vias when producing geometry", "If this option is given, no via geometry will be produced." @@ -793,6 +799,7 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options) load_options.set_option_by_name ("lefdef_config.lef_files", tl::Variant (m_lefdef_lef_files.begin (), m_lefdef_lef_files.end ())); load_options.set_option_by_name ("lefdef_config.read_lef_with_def", m_lefdef_read_lef_with_def); load_options.set_option_by_name ("lefdef_config.separate_groups", m_lefdef_separate_groups); + load_options.set_option_by_name ("lefdef_config.joined_paths", m_lefdef_joined_paths); load_options.set_option_by_name ("lefdef_config.map_file", m_lefdef_map_file); load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode); load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode); diff --git a/src/buddies/src/bd/bdReaderOptions.h b/src/buddies/src/bd/bdReaderOptions.h index a03b94481..1ca6e8dcd 100644 --- a/src/buddies/src/bd/bdReaderOptions.h +++ b/src/buddies/src/bd/bdReaderOptions.h @@ -185,6 +185,7 @@ private: std::vector m_lefdef_lef_files; bool m_lefdef_read_lef_with_def; bool m_lefdef_separate_groups; + bool m_lefdef_joined_paths; std::string m_lefdef_map_file; int m_lefdef_macro_resolution_mode; std::vector m_lefdef_lef_layout_files; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 989081b88..c72efceee 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -424,25 +424,25 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u } } -#if 0 - // single path - db::Path p (pt0, pt + 1, wxy, be, ee, false); - if (prop_id != 0) { - design.shapes (layer).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (layer).insert (p); - } -#else - // multipart paths - for (std::vector::const_iterator i = pt0; i != pt; ++i) { - db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false); + if (options ().joined_paths ()) { + // single path + db::Path p (pt0, pt + 1, wxy, be, ee, false); if (prop_id != 0) { design.shapes (layer).insert (db::object_with_properties (p, prop_id)); } else { design.shapes (layer).insert (p); } + } else { + // multipart paths + for (std::vector::const_iterator i = pt0; i != pt; ++i) { + db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false); + if (prop_id != 0) { + design.shapes (layer).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (layer).insert (p); + } + } } -#endif was_path_before = true; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 031b34726..dc706400e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -515,6 +515,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_special_routing_suffix (""), m_special_routing_datatype (0), m_separate_groups (false), + m_joined_paths (false), m_map_file (), m_macro_resolution_mode (0), m_read_lef_with_def (true), @@ -592,6 +593,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions & m_special_routing_datatype = d.m_special_routing_datatype; m_special_routing_datatypes = d.m_special_routing_datatypes; m_separate_groups = d.m_separate_groups; + m_joined_paths = d.m_joined_paths; m_map_file = d.m_map_file; m_macro_resolution_mode = d.m_macro_resolution_mode; m_lef_files = d.m_lef_files; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 84fdc7525..5b9518d1e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -874,6 +874,16 @@ public: m_separate_groups = f; } + bool joined_paths () const + { + return m_joined_paths; + } + + void set_joined_paths (bool f) + { + m_joined_paths = f; + } + const std::string &map_file () const { return m_map_file; @@ -1009,6 +1019,7 @@ private: std::map m_special_routing_suffixes; std::map m_special_routing_datatypes; bool m_separate_groups; + bool m_joined_paths; std::string m_map_file; unsigned int m_macro_resolution_mode; bool m_read_lef_with_def; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 758c19725..4d551936f 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -424,6 +424,7 @@ class LEFDEFFormatDeclaration tl::make_member (&LEFDEFReaderOptions::read_lef_with_def, &LEFDEFReaderOptions::set_read_lef_with_def, "read-lef-with-def") + tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) + tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") + + tl::make_member (&LEFDEFReaderOptions::joined_paths, &LEFDEFReaderOptions::set_joined_paths, "joined-paths") + tl::make_member (&LEFDEFReaderOptions::map_file, &LEFDEFReaderOptions::set_map_file, "map-file") ); } diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 6c1700eb6..1d2e685f1 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -880,6 +880,20 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n" "This property has been added in version 0.27.\n" ) + + gsi::method ("joined_paths", &db::LEFDEFReaderOptions::joined_paths, + "@brief Gets a value indicating whether to create joined paths for wires.\n" + "If this property is set to true, wires are represented by multi-segment paths as far as possible " + "(this will fail for 45 degree path segments for example). By defauls, wires are represented " + "by multiple straight segments.\n" + "\n" + "This property has been added in version 0.28.8.\n" + ) + + gsi::method ("joined_paths=", &db::LEFDEFReaderOptions::set_joined_paths, gsi::arg ("flag"), + "@brief Sets a value indicating whether to create joined paths for wires.\n" + "See \\joined_paths for details about this property.\n" + "\n" + "This property has been added in version 0.28.8.\n" + ) + gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file, "@brief Gets the layer map file to use.\n" "If a layer map file is given, the reader will pull the layer mapping from this file. The layer mapping rules " diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index d00f96cf6..2909c8638 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -6,7 +6,7 @@ 0 0 - 638 + 664 868 @@ -35,7 +35,7 @@ - 2 + 0 @@ -425,34 +425,21 @@ 0 - + Via cell name prefix - - - - - 0 - 0 - - + + - µm + Produce a parent cell per group - - - - Groups - - - - + Qt::Horizontal @@ -465,41 +452,7 @@ - - - - Produce a parent cell per group - - - - - - - Layout DBU - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - + QFrame::NoFrame @@ -523,6 +476,67 @@ + + + + + 0 + 0 + + + + µm + + + + + + + + 0 + 0 + + + + + + + + Layout DBU + + + + + + + Groups + + + + + + + Join paths + + + + + + + Produce multi-segment wire paths + + + + + + + + 0 + 0 + + + + @@ -598,7 +612,6 @@ - 50 false false @@ -773,7 +786,6 @@ - 50 false false false @@ -1011,8 +1023,8 @@ Otherwise it's looked up relative to the LEF or DEF file. 0 0 - 609 - 591 + 679 + 582 @@ -1595,6 +1607,7 @@ type ... move_lef_files_down dbu separate_groups + joined_paths prefix_via_cellname produce_net_names net_prop_name diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 4715181c6..e721d4458 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -521,6 +521,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_lef_labels_suffix (tl::to_string (suffix_lef_labels->text ())); data->set_lef_labels_datatype (datatype_lef_labels->text ().toInt ()); data->set_separate_groups (separate_groups->isChecked ()); + data->set_joined_paths (joined_paths->isChecked ()); data->set_read_lef_with_def (read_lef_with_def->isChecked ()); data->set_map_file (tl::to_string (mapfile_path->text ())); data->set_macro_resolution_mode (macro_resolution_mode->currentIndex ()); @@ -595,6 +596,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options suffix_lef_labels->setText (tl::to_qstring (data->lef_labels_suffix ())); datatype_lef_labels->setText (QString::number (data->lef_labels_datatype ())); separate_groups->setChecked (data->separate_groups ()); + joined_paths->setChecked (data->joined_paths ()); read_lef_with_def->setChecked (data->read_lef_with_def ()); mapfile_path->setText (tl::to_qstring (data->map_file ())); layer_map_mode->setCurrentIndex (data->map_file ().empty () ? 1 : 0); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 0dcc0c646..142b1d92d 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -976,3 +976,13 @@ TEST(206_lef_spacing) run_test (_this, "issue-1282", "read:a.lef", 0, default_options (), false); } +// issue-1345 +TEST(207_joined_paths) +{ + db::LEFDEFReaderOptions lefdef_opt = default_options (); + lefdef_opt.set_joined_paths (true); + run_test (_this, "issue-1345", "lef:in.lef+def:in.def", "au.oas.gz", lefdef_opt, false); + + run_test (_this, "issue-1345", "lef:in.lef+def:in.def", "au-nojoin.oas.gz", default_options (), false); +} + diff --git a/testdata/lefdef/issue-1345/au-nojoin.oas.gz b/testdata/lefdef/issue-1345/au-nojoin.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..21816fed74695374f4cb74dd9528ab838e1c1bde GIT binary patch literal 545 zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F; z;|1o9>4KX(8~>b$4qRRSKbqrK6n{_8gJqfAAn(M?z{@Cdn~~uL%S|8@X=E0;$uxm^A`tQd zo#|mJ{O7=q1U`<=J86j(f+drms&(J+KPIB*w!)yf$4Z%9*?#d1M&=pX+RIL!Ik7`P zN1a=!#fXs^;vN}s296Vq%$#AKj`6-m@xF#2fenmIjLl4p42;T*#f+;R4CduxWH!_@V0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F; z;|1o9>4KX(8~>b$4qRRSKbqrK6n{_8gJqfAAn(M?z{@Cdn~~uL%S|8@X=E0;$uxm^A`tQd zooQ_>{O7=q1U`<=J86j(f+drms&(J+KPIBbrq*G=+}vZO%&u&|c!sJm^W{U9J>1V7 zOiwT|Fhg7;BhJ8af{~ds%+oR6*C^iC5G1gHk%_U9iIIU(nX#C$o{^zpgaHNy0PAVp A3IG5A literal 0 HcmV?d00001 diff --git a/testdata/lefdef/issue-1345/in.def b/testdata/lefdef/issue-1345/in.def new file mode 100644 index 000000000..423d5a4be --- /dev/null +++ b/testdata/lefdef/issue-1345/in.def @@ -0,0 +1,16 @@ +VERSION 5.6 ; +NAMESCASESENSITIVE ON ; +DIVIDERCHAR "/" ; +BUSBITCHARS "<>" ; +DESIGN SMALL ; +UNITS DISTANCE MICRONS 100 ; + +DIEAREA ( -30 -30 ) ( 1030 1030 ) ; + +NETS 1 ; +- TOP ++ ROUTED M1 ( 0 0 ) ( 1000 * ) ( * 1000 ) M2_M1 + NEW M2 ( 1000 1000 ) ( 0 * ) ( 0 0 ) ; +END NETS + +END DESIGN diff --git a/testdata/lefdef/issue-1345/in.lef b/testdata/lefdef/issue-1345/in.lef new file mode 100644 index 000000000..a0359f764 --- /dev/null +++ b/testdata/lefdef/issue-1345/in.lef @@ -0,0 +1,40 @@ +VERSION 5.7 ; +NAMESCASESENSITIVE ON ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; +UNITS + DATABASE MICRONS 1000 ; +END UNITS + +USEMINSPACING OBS ON ; +USEMINSPACING PIN OFF ; +CLEARANCEMEASURE EUCLIDEAN ; + +MANUFACTURINGGRID 0.05 ; + +LAYER M1 + TYPE ROUTING ; + DIRECTION HORIZONTAL ; + WIDTH 0.2 ; +END M1 + +LAYER V2 + TYPE CUT ; +END V2 + +LAYER M2 + TYPE ROUTING ; + DIRECTION VERTICAL ; + WIDTH 0.2 ; +END M2 + +VIA M2_M1 DEFAULT + LAYER M1 ; + RECT -0.300 -0.300 0.300 0.300 ; + LAYER V2 ; + RECT -0.200 -0.200 0.200 0.200 ; + LAYER M2 ; + RECT -0.300 -0.300 0.300 0.300 ; +END M2_M1 + +END LIBRARY From 6c7064fa23d5e872e7698ec4f646d39782fb9921 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 01:37:41 +0200 Subject: [PATCH 2/7] Implemented fix for issue #1357 (RBA/pya binding for QObject#findChildren) --- scripts/mkqtdecl_common/common.conf | 45 ++++++++++++++++++++++++-- src/gsiqt/qt4/QtCore/gsiDeclQObject.cc | 43 ++++++++++++++++++++++-- src/gsiqt/qt5/QtCore/gsiDeclQObject.cc | 43 ++++++++++++++++++++++-- src/gsiqt/qt6/QtCore/gsiDeclQObject.cc | 43 ++++++++++++++++++++++-- testdata/ruby/qtbinding.rb | 22 +++++++++++++ 5 files changed, 187 insertions(+), 9 deletions(-) diff --git a/scripts/mkqtdecl_common/common.conf b/scripts/mkqtdecl_common/common.conf index fe4f2da1f..378d6e1c6 100644 --- a/scripts/mkqtdecl_common/common.conf +++ b/scripts/mkqtdecl_common/common.conf @@ -62,15 +62,54 @@ DECL end # -------------------------------------------------------------- -# Provides the definitions for QObject::findChild +# Provides the definitions for QObject::findChild and QObject::findChildren def add_native_impl_QObject_findChild() # alternative implementation for QObject::findChild using QObject for T add_native_impl("QObject", <<'CODE', <<'DECL') - QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); } + +#if QT_VERSION < 0x50000 + + QObject *find_child_impl (QObject *object, const QString &name) + { + return object->findChild (name); + } + QList find_children_impl (QObject *object, const QString &name) + { + return object->findChildren (name); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re) + { + return object->findChildren (re); + } +#else + +#include + + QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChild (name, options); + } + QList find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChildren (name, options); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options) + { + return object->findChildren (re, options); + } +#endif CODE - gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).") +#if QT_VERSION < 0x50000 + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).") +#else + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +#endif DECL end diff --git a/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc index 81e440d14..2a9929f86 100644 --- a/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc @@ -51,7 +51,38 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g ret.write (QObject::staticMetaObject); } - QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); } + +#if QT_VERSION < 0x50000 + + QObject *find_child_impl (QObject *object, const QString &name) + { + return object->findChild (name); + } + QList find_children_impl (QObject *object, const QString &name) + { + return object->findChildren (name); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re) + { + return object->findChildren (re); + } +#else + +#include + + QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChild (name, options); + } + QList find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChildren (name, options); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options) + { + return object->findChildren (re, options); + } +#endif // bool QObject::blockSignals(bool b) @@ -757,7 +788,15 @@ static gsi::Methods methods_QObject () { } qt_gsi::QtNativeClass decl_QObject ("QtCore", "QObject_Native", - gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).") +#if QT_VERSION < 0x50000 + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).") +#else + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +#endif + methods_QObject (), "@hide\n@alias QObject"); diff --git a/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc index 8b2376519..aa5d7c29d 100644 --- a/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc @@ -52,7 +52,38 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g ret.write (QObject::staticMetaObject); } - QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); } + +#if QT_VERSION < 0x50000 + + QObject *find_child_impl (QObject *object, const QString &name) + { + return object->findChild (name); + } + QList find_children_impl (QObject *object, const QString &name) + { + return object->findChildren (name); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re) + { + return object->findChildren (re); + } +#else + +#include + + QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChild (name, options); + } + QList find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChildren (name, options); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options) + { + return object->findChildren (re, options); + } +#endif // bool QObject::blockSignals(bool b) @@ -813,7 +844,15 @@ static gsi::Methods methods_QObject () { } qt_gsi::QtNativeClass decl_QObject ("QtCore", "QObject_Native", - gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).") +#if QT_VERSION < 0x50000 + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).") +#else + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +#endif + methods_QObject (), "@hide\n@alias QObject"); diff --git a/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc index 5220ea53d..aafe61ded 100644 --- a/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc @@ -52,7 +52,38 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g ret.write (QObject::staticMetaObject); } - QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); } + +#if QT_VERSION < 0x50000 + + QObject *find_child_impl (QObject *object, const QString &name) + { + return object->findChild (name); + } + QList find_children_impl (QObject *object, const QString &name) + { + return object->findChildren (name); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re) + { + return object->findChildren (re); + } +#else + +#include + + QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChild (name, options); + } + QList find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options) + { + return object->findChildren (name, options); + } + QList find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options) + { + return object->findChildren (re, options); + } +#endif // bool QObject::blockSignals(bool b) @@ -771,7 +802,15 @@ static gsi::Methods methods_QObject () { } qt_gsi::QtNativeClass decl_QObject ("QtCore", "QObject_Native", - gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).") +#if QT_VERSION < 0x50000 + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).") +#else + gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") + + gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +#endif + methods_QObject (), "@hide\n@alias QObject"); diff --git a/testdata/ruby/qtbinding.rb b/testdata/ruby/qtbinding.rb index 356aaa29e..b66e090fd 100644 --- a/testdata/ruby/qtbinding.rb +++ b/testdata/ruby/qtbinding.rb @@ -767,6 +767,28 @@ class QtBinding_TestClass < TestBase end + def test_60 + + # findChild, findChildren + + w = RBA::QWidget::new + w.objectName = "w" + w1 = RBA::QWidget::new(w) + w1.objectName = "w1" + w2 = RBA::QWidget::new(w1) + w2.objectName = "w2" + + assert_equal(w.findChild.objectName, "w1") + assert_equal(w.findChild("w2").objectName, "w2") + + assert_equal(w.findChildren().collect { |c| c.objectName }.join(","), "w1,w2") + assert_equal(w.findChildren("w2").collect { |c| c.objectName }.join(","), "w2") + + assert_equal(w.findChildren(RBA::QRegularExpression::new("^.2$")).collect { |c| c.objectName }.join(","), "w2") + assert_equal(w.findChildren(RBA::QRegularExpression::new("^w.$")).collect { |c| c.objectName }.join(","), "w1,w2") + + end + end load("test_epilogue.rb") From 33d16a1e28c20e1843dd3a8eedb662679e67391c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 15:34:11 +0200 Subject: [PATCH 3/7] Implemented fix for issue #1324 --- src/layui/layui/layLayerControlPanel.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/layui/layui/layLayerControlPanel.cc b/src/layui/layui/layLayerControlPanel.cc index 31b3bacf2..8f9eb165c 100644 --- a/src/layui/layui/layLayerControlPanel.cc +++ b/src/layui/layui/layLayerControlPanel.cc @@ -1752,8 +1752,21 @@ set_hidden_flags_rec (LayerTreeModel *model, QTreeView *tree_view, const QModelI } } else { - tree_view->setRowHidden (r, parent, false); + set_hidden_flags_rec (model, tree_view, index); + + // hide a group entry if all children are hidden + + bool hide = true; + int rrows = model->rowCount (index); + for (int rr = 0; rr < rrows; ++rr) { + if (! tree_view->isRowHidden (rr, index)) { + hide = false; + } + } + + tree_view->setRowHidden (r, parent, hide); + } } From 8704fa1b864afaca181bfc1c71775f914c7665a5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 16:04:42 +0200 Subject: [PATCH 4/7] Solved issue #1219: 'close' button works now in macro IDE, printing name of macro which is run to avoid confusion between 'run current' and 'run this' --- src/lay/lay/layMacroEditorDialog.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc index 3266b7c60..e75c60dfa 100644 --- a/src/lay/lay/layMacroEditorDialog.cc +++ b/src/lay/lay/layMacroEditorDialog.cc @@ -399,6 +399,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection replaceText->setPlaceholderText (tr ("Replace text ...")); #endif + connect (closeButton, SIGNAL (clicked ()), this, SLOT (close_button_clicked ())); connect (forwardButton, SIGNAL (clicked ()), this, SLOT (forward ())); connect (backwardButton, SIGNAL (clicked ()), this, SLOT (backward ())); @@ -2362,7 +2363,7 @@ END_PROTECTED void MacroEditorDialog::tab_close_requested (int index) { - if (m_in_exec) { + if (m_in_exec || index < 0) { return; } @@ -3736,8 +3737,12 @@ MacroEditorDialog::run (int stop_stack_depth, lym::Macro *macro) set_run_macro (macro); try { + + write_str (tl::sprintf (tl::to_string (tr ("Running macro %s\n")), macro->path ()).c_str (), OS_echo); + macro->run (); m_stop_stack_depth = -1; + } catch (tl::ExitException &) { m_stop_stack_depth = -1; // .. ignore exit exceptions .. From d40ed70fb9435a591c9dc8e9f65323e4ecab2de4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 18:44:20 +0200 Subject: [PATCH 5/7] Implemented a solution for issue #1348 (Reload Files popup prevents closing KLayout): now the reload notification is shown as a notification bar at the top of the layout view --- src/lay/lay/layMainWindow.cc | 77 ++++----------- src/layview/layview/layLayoutView_qt.cc | 123 ++++++++++++++++++++++++ src/layview/layview/layLayoutView_qt.h | 111 +++++++++++++++++++++ 3 files changed, 255 insertions(+), 56 deletions(-) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 277a702eb..390263bb6 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -590,12 +590,7 @@ MainWindow::file_changed_timer () } - // Prevent recursive signals - m_file_changed_timer.blockSignals (true); - - std::set reloaded_files; - -BEGIN_PROTECTED + std::set notified_files; // Make the names unique std::sort (m_changed_files.begin (), m_changed_files.end ()); @@ -605,68 +600,38 @@ BEGIN_PROTECTED return; } - QString msg; - - if (m_changed_files.size () == 1) { - msg = QObject::tr ("The following file has been changed on disk:\n\n"); - for (std::vector::const_iterator f = m_changed_files.begin (); f != m_changed_files.end (); ++f) { - msg += QString::fromUtf8 (" %1\n").arg (*f); - } - msg += tr ("\nReload this file?"); - } else { - msg = QObject::tr ("The following files have been changed on disk:\n\n"); - for (std::vector::const_iterator f = m_changed_files.begin (); f != m_changed_files.end (); ++f) { - msg += QString::fromUtf8 (" %1\n").arg (*f); - } - msg += tr ("\nReload these files?"); - } + // adds a notification to the involved views that the file has changed std::vector changed_files; changed_files.swap (m_changed_files); - if (QMessageBox::question (this, tr ("Reload Files"), msg, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + std::map > > views_per_file; - m_file_changed_timer.blockSignals (false); - - std::map > views_per_file; - - for (std::vector::iterator v = mp_views.begin (); v != mp_views.end (); ++v) { - for (int cv = 0; cv < int ((*v)->view ()->cellviews ()); ++cv) { - views_per_file [tl::to_qstring ((*v)->view ()->cellview (cv)->filename ())] = std::make_pair (*v, cv); - } + for (auto v = mp_views.begin (); v != mp_views.end (); ++v) { + for (int cv = 0; cv < int ((*v)->view ()->cellviews ()); ++cv) { + views_per_file [tl::to_qstring ((*v)->view ()->cellview (cv)->filename ())].push_back (std::make_pair (*v, cv)); } - - for (std::vector::const_iterator f = changed_files.begin (); f != changed_files.end (); ++f) { - std::map >::const_iterator v = views_per_file.find (*f); - if (v != views_per_file.end ()) { - v->second.first->view ()->reload_layout (v->second.second); - reloaded_files.insert (*f); - } - } - } -END_PROTECTED + for (auto f = changed_files.begin (); f != changed_files.end (); ++f) { - m_file_changed_timer.blockSignals (false); + auto v = views_per_file.find (*f); + if (v != views_per_file.end ()) { - // While the message box was open, new request might have collected - remove - // the ones we just reloaded and restart the timer - if (! m_changed_files.empty ()) { + for (auto w = v->second.begin (); w != v->second.end (); ++w) { + + std::string title; + if (w->first->view ()->cellviews () > 1) { + title = tl::sprintf (tl::to_string (tr ("Layout file @%d (%s) has changed on disk")), w->second + 1, tl::filename (tl::to_string (*f))); + } else { + title = tl::sprintf (tl::to_string (tr ("Layout file (%s) has changed on disk")), tl::filename (tl::to_string (*f))); + } + + lay::LayoutViewNotification n ("reload", title, tl::Variant (tl::to_string (*f))); + n.add_action ("reload", tl::to_string (tr ("Reload"))); + w->first->add_notification (n); - std::vector changed_files; - changed_files.swap (m_changed_files); - for (std::vector::const_iterator f = changed_files.begin (); f != changed_files.end (); ++f) { - if (reloaded_files.find (*f) == reloaded_files.end ()) { - m_changed_files.push_back (*f); } - } - - if (! m_changed_files.empty ()) { - - // Wait a little to let more to allow for more reload requests to collect - m_file_changed_timer.setInterval (300); - m_file_changed_timer.start (); } diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 9b3f04286..8660fe15d 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "tlInternational.h" #include "tlExpression.h" @@ -76,6 +78,7 @@ #include "layEditorOptionsPages.h" #include "layUtils.h" #include "layPropertiesDialog.h" +#include "layQtTools.h" #include "dbClipboard.h" #include "dbLayout.h" #include "dbLayoutUtils.h" @@ -94,12 +97,70 @@ namespace lay { +// ------------------------------------------------------------- +// LayoutViewNotificationWidget implementation + +LayoutViewNotificationWidget::LayoutViewNotificationWidget (LayoutViewWidget *parent, const LayoutViewNotification *notification) + : QFrame (parent), mp_parent (parent), mp_notification (notification) +{ + setBackgroundRole (QPalette::ToolTipBase); + setAutoFillBackground (true); + + QHBoxLayout *layout = new QHBoxLayout (this); + layout->setContentsMargins (4, 4, 4, 4); + + QLabel *title_label = new QLabel (this); + layout->addWidget (title_label, 1); + title_label->setText (tl::to_qstring (notification->title ())); + title_label->setForegroundRole (QPalette::ToolTipText); + title_label->setWordWrap (true); + activate_help_links (title_label); + + for (auto a = notification->actions ().begin (); a != notification->actions ().end (); ++a) { + + QPushButton *pb = new QPushButton (this); + layout->addWidget (pb); + + pb->setText (tl::to_qstring (a->second)); + m_action_buttons.insert (std::make_pair (pb, a->first)); + connect (pb, SIGNAL (clicked ()), this, SLOT (action_triggered ())); + + } + + QToolButton *close_button = new QToolButton (); + close_button->setIcon (QIcon (":clear_edit_16px.png")); + close_button->setAutoRaise (true); + layout->addWidget (close_button); + + connect (close_button, SIGNAL (clicked ()), this, SLOT (close_triggered ())); +} + +void +LayoutViewNotificationWidget::action_triggered () +{ + auto a = m_action_buttons.find (sender ()); + if (a != m_action_buttons.end ()) { + mp_parent->notification_action (*mp_notification, a->second); + } +} + +void +LayoutViewNotificationWidget::close_triggered () +{ + mp_parent->remove_notification (*mp_notification); +} + // ------------------------------------------------------------- // LayoutViewWidget implementation LayoutViewWidget::LayoutViewWidget (db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options) : QFrame (parent), mp_view (0) { + mp_layout = new QVBoxLayout (this); + mp_layout->setContentsMargins (0, 0, 0, 0); + mp_layout->setSpacing (0); + mp_layout->addStretch (1); + // NOTE: construction the LayoutView may trigger events (script code executed etc.) which must // not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only // after the LayoutView is successfully constructed. @@ -110,6 +171,11 @@ LayoutViewWidget::LayoutViewWidget (db::Manager *mgr, bool editable, lay::Plugin LayoutViewWidget::LayoutViewWidget (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options) : QFrame (parent), mp_view (0) { + mp_layout = new QVBoxLayout (this); + mp_layout->setContentsMargins (0, 0, 0, 0); + mp_layout->setSpacing (0); + mp_layout->addStretch (1); + // NOTE: construction the LayoutView may trigger events (script code executed etc.) which must // not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only // after the LayoutView is successfully constructed. @@ -124,6 +190,55 @@ LayoutViewWidget::~LayoutViewWidget () delete view; } +void +LayoutViewWidget::add_notification (const LayoutViewNotification ¬ificaton) +{ + if (m_notification_widgets.find (¬ificaton) == m_notification_widgets.end ()) { + m_notifications.push_back (notificaton); + QWidget *w = new LayoutViewNotificationWidget (this, &m_notifications.back ()); + m_notification_widgets.insert (std::make_pair (&m_notifications.back (), w)); + mp_layout->insertWidget (0, w); + } +} + +void +LayoutViewWidget::remove_notification (const LayoutViewNotification ¬ification) +{ + auto nw = m_notification_widgets.find (¬ification); + if (nw != m_notification_widgets.end ()) { + + nw->second->deleteLater (); + m_notification_widgets.erase (nw); + + for (auto n = m_notifications.begin (); n != m_notifications.end (); ++n) { + if (*n == notification) { + m_notifications.erase (n); + break; + } + } + + } +} + +void +LayoutViewWidget::notification_action (const LayoutViewNotification ¬ification, const std::string &action) +{ + if (action == "reload") { + + std::string fn = notification.parameter ().to_string (); + + for (unsigned int cvi = 0; cvi < mp_view->cellviews (); ++cvi) { + const lay::CellView &cv = mp_view->cellview (cvi); + if (cv->filename () == fn) { + mp_view->reload_layout (cvi); + } + } + + remove_notification (notification); + + } +} + void LayoutViewWidget::view_deleted (lay::LayoutView *view) { @@ -135,6 +250,14 @@ LayoutViewWidget::view_deleted (lay::LayoutView *view) mp_view = new LayoutView (view->manager (), view->is_editable (), view->plugin_parent (), this, view->options ()); } +void +LayoutViewWidget::resizeEvent (QResizeEvent *) +{ + if (mp_view && mp_view->canvas ()) { + mp_view->canvas ()->resize (width (), height ()); + } +} + QSize LayoutViewWidget::sizeHint () const { diff --git a/src/layview/layview/layLayoutView_qt.h b/src/layview/layview/layLayoutView_qt.h index 294f85f70..b956c9348 100644 --- a/src/layview/layview/layLayoutView_qt.h +++ b/src/layview/layview/layLayoutView_qt.h @@ -57,6 +57,7 @@ #include #include +#include class QSpinBox; @@ -683,6 +684,91 @@ private: void activate_editor_option_pages (); }; +/** + * @brief Descriptor for a notification inside the layout view + * + * Notifications are popups added at the top of the view to indicate need for reloading for example. + * Notifications have a name, a title, optional actions (id, title) and a parameter (e.g. file path to reload). + * Actions are mapped to QPushButtons. + */ +class LAYVIEW_PUBLIC LayoutViewNotification +{ +public: + LayoutViewNotification (const std::string &name, const std::string &title, const tl::Variant ¶meter = tl::Variant ()) + : m_name (name), m_title (title), m_parameter (parameter) + { + // .. nothing yet .. + } + + void add_action (const std::string &name, const std::string &title) + { + m_actions.push_back (std::make_pair (name, title)); + } + + const std::vector > &actions () const + { + return m_actions; + } + + const std::string &name () const + { + return m_name; + } + + const std::string &title () const + { + return m_title; + } + + const tl::Variant ¶meter () const + { + return m_parameter; + } + + bool operator<(const LayoutViewNotification &other) const + { + if (m_name != other.name ()) { + return m_name < other.name (); + } + return m_parameter < other.parameter (); + } + + bool operator==(const LayoutViewNotification &other) const + { + if (m_name != other.name ()) { + return false; + } + return m_parameter == other.parameter (); + } + +private: + std::string m_name; + std::string m_title; + tl::Variant m_parameter; + std::vector > m_actions; +}; + +/** + * @brief A widget representing a notification + */ +class LAYVIEW_PUBLIC LayoutViewNotificationWidget + : public QFrame +{ +Q_OBJECT + +public: + LayoutViewNotificationWidget (LayoutViewWidget *parent, const LayoutViewNotification *notification); + +private slots: + void action_triggered (); + void close_triggered (); + +private: + LayoutViewWidget *mp_parent; + const LayoutViewNotification *mp_notification; + std::map m_action_buttons; +}; + /** * @brief The layout view widget * @@ -710,6 +796,16 @@ public: */ ~LayoutViewWidget (); + /** + * @brief Adds a notification + */ + void add_notification (const LayoutViewNotification ¬ificaton); + + /** + * @brief Removes a notification + */ + void remove_notification (const LayoutViewNotification ¬ificaton); + /** * @brief Gets the LayoutView embedded into this widget */ @@ -817,10 +913,25 @@ signals: private: friend class LayoutView; + friend class LayoutViewNotificationWidget; void view_deleted (lay::LayoutView *view); + void notification_action (const LayoutViewNotification ¬ification, const std::string &action); + + void resizeEvent (QResizeEvent *event); + + struct CompareNotificationPointers + { + bool operator() (const LayoutViewNotification *a, const LayoutViewNotification *b) const + { + return *a < *b; + } + }; LayoutView *mp_view; + QVBoxLayout *mp_layout; + std::list m_notifications; + std::map m_notification_widgets; }; /** From 67db8dfc96c9543880e2c84b60c48f8fa2255cf9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 19:41:37 +0200 Subject: [PATCH 6/7] Trying to fix Qt4 builds --- scripts/mkqtdecl_common/common.conf | 4 +++- src/gsiqt/qt4/QtCore/gsiDeclQObject.cc | 4 +++- src/gsiqt/qt5/QtCore/gsiDeclQObject.cc | 4 +++- src/gsiqt/qt6/QtCore/gsiDeclQObject.cc | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/mkqtdecl_common/common.conf b/scripts/mkqtdecl_common/common.conf index 378d6e1c6..1a07a185b 100644 --- a/scripts/mkqtdecl_common/common.conf +++ b/scripts/mkqtdecl_common/common.conf @@ -71,6 +71,8 @@ def add_native_impl_QObject_findChild() #if QT_VERSION < 0x50000 +#include + QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); @@ -79,7 +81,7 @@ def add_native_impl_QObject_findChild() { return object->findChildren (name); } - QList find_children_impl2 (QObject *object, const QRegularExpression &re) + QList find_children_impl2 (QObject *object, const QRegExp &re) { return object->findChildren (re); } diff --git a/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc index 2a9929f86..2ab3add1e 100644 --- a/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt4/QtCore/gsiDeclQObject.cc @@ -54,6 +54,8 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g #if QT_VERSION < 0x50000 +#include + QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); @@ -62,7 +64,7 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g { return object->findChildren (name); } - QList find_children_impl2 (QObject *object, const QRegularExpression &re) + QList find_children_impl2 (QObject *object, const QRegExp &re) { return object->findChildren (re); } diff --git a/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc index aa5d7c29d..70ccedc94 100644 --- a/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt5/QtCore/gsiDeclQObject.cc @@ -55,6 +55,8 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g #if QT_VERSION < 0x50000 +#include + QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); @@ -63,7 +65,7 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g { return object->findChildren (name); } - QList find_children_impl2 (QObject *object, const QRegularExpression &re) + QList find_children_impl2 (QObject *object, const QRegExp &re) { return object->findChildren (re); } diff --git a/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc b/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc index aafe61ded..f4a89d144 100644 --- a/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc +++ b/src/gsiqt/qt6/QtCore/gsiDeclQObject.cc @@ -55,6 +55,8 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g #if QT_VERSION < 0x50000 +#include + QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild (name); @@ -63,7 +65,7 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g { return object->findChildren (name); } - QList find_children_impl2 (QObject *object, const QRegularExpression &re) + QList find_children_impl2 (QObject *object, const QRegExp &re) { return object->findChildren (re); } From 77ce1d48255dc8d7a45a5e3e843479ac8d9a9e86 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 May 2023 21:11:41 +0200 Subject: [PATCH 7/7] Another fix for Qt4 --- testdata/ruby/qtbinding.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testdata/ruby/qtbinding.rb b/testdata/ruby/qtbinding.rb index b66e090fd..f0164c397 100644 --- a/testdata/ruby/qtbinding.rb +++ b/testdata/ruby/qtbinding.rb @@ -784,8 +784,15 @@ class QtBinding_TestClass < TestBase assert_equal(w.findChildren().collect { |c| c.objectName }.join(","), "w1,w2") assert_equal(w.findChildren("w2").collect { |c| c.objectName }.join(","), "w2") - assert_equal(w.findChildren(RBA::QRegularExpression::new("^.2$")).collect { |c| c.objectName }.join(","), "w2") - assert_equal(w.findChildren(RBA::QRegularExpression::new("^w.$")).collect { |c| c.objectName }.join(","), "w1,w2") + begin + # Qt5++ + re_cls = RBA::QRegularExpression + rescue => ex + # Qt4 + re_cls = RBA::QRegExp + end + assert_equal(w.findChildren(re_cls::new("^.2$")).collect { |c| c.objectName }.join(","), "w2") + assert_equal(w.findChildren(re_cls::new("^w.$")).collect { |c| c.objectName }.join(","), "w1,w2") end