From bbaaa14b2c8ef686b454823a5286ff0b77c300ad Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 22 Nov 2025 23:57:40 +0100 Subject: [PATCH 1/2] Bringing 'save all' on the same level than 'same' - Taking the technology's settings for save options - Deploying "libname", e.g. for GDS2 --- src/lay/lay/layMainWindow.cc | 43 ++++++++++++++++------------ src/laybasic/laybasic/layCellView.cc | 26 ----------------- src/laybasic/laybasic/layCellView.h | 9 ------ 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index b54499056..b1fa11141 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2277,6 +2277,29 @@ MainWindow::cm_save_as () do_save (true); } +static db::SaveLayoutOptions +get_save_options_from_cv (const lay::CellView &cv) +{ + db::SaveLayoutOptions options = cv->save_options (); + if (!cv->save_options_valid () && cv->technology ()) { + options = cv->technology ()->save_layout_options (); + options.set_format (cv->save_options ().format ()); + } + + // preconfigure options with current values + + options.set_dbu (cv->layout ().dbu ()); + + if (cv->layout ().has_meta_info ("libname")) { + tl::Variant libname = cv->layout ().meta_info ("libname").value; + if (libname.is_a_string ()) { + options.set_libname (libname.to_stdstring ()); + } + } + + return options; +} + void MainWindow::do_save (bool as) { @@ -2309,22 +2332,7 @@ MainWindow::do_save (bool as) // - if the layout's save options are valid we take the options from there, otherwise we take the options from the technology // - on "save as" we let the user edit the options - db::SaveLayoutOptions options = cv->save_options (); - if (!cv->save_options_valid () && cv->technology ()) { - options = cv->technology ()->save_layout_options (); - options.set_format (cv->save_options ().format ()); - } - - // preconfigure options with current values - - options.set_dbu (cv->layout ().dbu ()); - - if (cv->layout ().has_meta_info ("libname")) { - tl::Variant libname = cv->layout ().meta_info ("libname").value; - if (libname.is_a_string ()) { - options.set_libname (libname.to_stdstring ()); - } - } + db::SaveLayoutOptions options = get_save_options_from_cv (cv); if (as || options.format ().empty ()) { options.set_format_from_filename (fn); @@ -2362,8 +2370,7 @@ MainWindow::cm_save_all () if (! fn.empty () || mp_layout_fdia->get_save (fn, tl::to_string (tr ("Save Layout '%1'").arg (tl::to_qstring (cv->name ()))))) { - db::SaveLayoutOptions options (cv->save_options ()); - options.set_dbu (cv->layout ().dbu ()); + db::SaveLayoutOptions options = get_save_options_from_cv (cv); if (options.format ().empty ()) { options.set_format_from_filename (fn); diff --git a/src/laybasic/laybasic/layCellView.cc b/src/laybasic/laybasic/layCellView.cc index 84cbde12c..4249f91db 100644 --- a/src/laybasic/laybasic/layCellView.cc +++ b/src/laybasic/laybasic/layCellView.cc @@ -300,32 +300,6 @@ LayoutHandle::set_save_options (const db::SaveLayoutOptions &options, bool valid m_save_options_valid = valid; } -void -LayoutHandle::update_save_options (db::SaveLayoutOptions &options) -{ -#if defined(HAVE_QT) - for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { - - const lay::StreamWriterPluginDeclaration *decl = dynamic_cast (&*cls); - if (! decl || decl->options_alias ()) { - continue; - } - - std::unique_ptr specific_options; - if (options.get_options (decl->format_name ())) { - specific_options.reset (options.get_options (decl->format_name ())->clone ()); - } else { - specific_options.reset (decl->create_specific_options ()); - } - - if (specific_options.get ()) { - options.set_options (specific_options.release ()); - } - - } -#endif -} - void LayoutHandle::save_as (const std::string &fn, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update, int keep_backups) { diff --git a/src/laybasic/laybasic/layCellView.h b/src/laybasic/laybasic/layCellView.h index 661d6c8c1..0b5adadd1 100644 --- a/src/laybasic/laybasic/layCellView.h +++ b/src/laybasic/laybasic/layCellView.h @@ -242,15 +242,6 @@ public: return m_save_options; } - /** - * @brief Updates the given save options with attributes from this cell view - * - * Some formats will initialize attributes from the cell view and the layout's - * metadata (example: libname of GDS2). This method will update the options - * if the layout provides attributes for initializing the latter. - */ - void update_save_options (db::SaveLayoutOptions &options); - /** * @brief Gets a flag indicating whether the save options are valid * From bc835adf648fe86ef159f16ce9ad2b61bfbc4082 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 27 Nov 2025 21:57:13 +0100 Subject: [PATCH 2/2] Fixed issue #2221 (restoring 'save' behavior on 'save all') 'save all' now behaves like 'save' on all layouts by respecting the application-wide writer options. In addition, a weird feature was fixed: when using 'save' for the first time, old versions were freezing the writer options and changing the application-wide options did not have an effect on views after they were saved the first time. Now, this behavior only applies to "save as" and a popup is shown in the top of the layout view indicating that from now on the special options apply. This way, special options can be picked in "save as" and they will remain valid during the next "save". --- src/lay/lay/layMainWindow.cc | 21 ++++--- src/laybasic/laybasic/layCellView.cc | 2 - src/laybasic/laybasic/layLayoutViewBase.h | 72 ++++++++++++++++++++++ src/layview/layview/layLayoutView_qt.cc | 8 +++ src/layview/layview/layLayoutView_qt.h | 75 +++-------------------- 5 files changed, 100 insertions(+), 78 deletions(-) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index b1fa11141..9b1b12c60 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2345,7 +2345,18 @@ MainWindow::do_save (bool as) } current_view ()->save_as ((unsigned int) cv_index, fn, om, options, true, m_keep_backups); - add_mru (fn, current_view ()->cellview (cv_index)->tech_name ()); + add_mru (fn, cv->tech_name ()); + + if (as) { + + lay::LayoutViewNotification n ("reload", tl::to_string (tr ("The next 'save' operations will use the writer options you have picked, instead of the application-wide ones."))); + current_view ()->add_notification (n); + + // freeze writer options in the 'save_as' case, so we can do another "save" and get the + // selected options again + cv->set_save_options (options, true); + + } } @@ -2378,14 +2389,6 @@ MainWindow::cm_save_all () tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto; - // initialize the specific options from the configuration if required - for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { - const StreamWriterPluginDeclaration *decl = dynamic_cast (&*cls); - if (decl) { - options.set_options (decl->create_specific_options ()); - } - } - view (view_index)->save_as (cv_index, fn, om, options, true, m_keep_backups); add_mru (fn, cv->tech_name ()); diff --git a/src/laybasic/laybasic/layCellView.cc b/src/laybasic/laybasic/layCellView.cc index 4249f91db..df8fb73a3 100644 --- a/src/laybasic/laybasic/layCellView.cc +++ b/src/laybasic/laybasic/layCellView.cc @@ -305,8 +305,6 @@ LayoutHandle::save_as (const std::string &fn, tl::OutputStream::OutputStreamMode { if (update) { - m_save_options = options; - m_save_options_valid = true; // We must not load with the original options after we have saved the file - hence we reset the // reader options. m_load_options = db::LoadLayoutOptions (); diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index b0ad6d28e..db17f7148 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -149,6 +149,70 @@ struct LAYBASIC_PUBLIC LayerDisplayProperties std::string name; }; +/** + * @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 LAYBASIC_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 The layout view object * @@ -279,6 +343,14 @@ public: */ virtual void cut (); + /** + * @brief Adds a notification + */ + virtual void add_notification (const LayoutViewNotification & /*notification*/) + { + // the base implementation does nothing + } + /** * @brief Gets the explicit title string of the view * diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 55cad6857..b58214835 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -453,6 +453,14 @@ LayoutView::LayoutView (lay::LayoutView *source, db::Manager *manager, bool edit LayoutView::set_active_cellview_index (source->active_cellview_index ()); } +void +LayoutView::add_notification (const LayoutViewNotification ¬ification) +{ + if (mp_widget) { + mp_widget->add_notification (notification); + } +} + bool LayoutView::event_filter (QObject *obj, QEvent *event, bool &taken) { diff --git a/src/layview/layview/layLayoutView_qt.h b/src/layview/layview/layLayoutView_qt.h index 837146a9a..6f2b3f0f8 100644 --- a/src/layview/layview/layLayoutView_qt.h +++ b/src/layview/layview/layLayoutView_qt.h @@ -1,4 +1,4 @@ - +# /* KLayout Layout Viewer @@ -149,6 +149,11 @@ public: */ ~LayoutView (); + /** + * @brief Adds a notification + */ + virtual void add_notification (const LayoutViewNotification ¬ification); + /** * @brief Gets the widget object that view is embedded in */ @@ -695,70 +700,6 @@ 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 */ @@ -810,12 +751,12 @@ public: /** * @brief Adds a notification */ - void add_notification (const LayoutViewNotification ¬ificaton); + void add_notification (const LayoutViewNotification ¬ification); /** * @brief Removes a notification */ - void remove_notification (const LayoutViewNotification ¬ificaton); + void remove_notification (const LayoutViewNotification ¬ification); /** * @brief Gets the LayoutView embedded into this widget