From acfc2aae09c4e791ac15bf67ea925792f7dcde8e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 25 Aug 2025 00:04:44 +0200 Subject: [PATCH] WIP: preparing integration of editor options pages and config pages into plugin API --- src/laybasic/laybasic/gsiDeclLayPlugin.cc | 280 ++++++++++++++++-- .../laybasic}/layEditorOptionsPage.cc | 14 + .../laybasic}/layEditorOptionsPage.h | 19 +- .../laybasic}/layEditorOptionsPages.cc | 17 -- .../laybasic}/layEditorOptionsPages.h | 4 +- src/laybasic/laybasic/layPlugin.cc | 18 +- src/laybasic/laybasic/layPlugin.h | 12 + src/laybasic/laybasic/layViewObject.cc | 9 +- src/laybasic/laybasic/layViewObject.h | 5 + src/laybasic/laybasic/laybasic.pro | 4 + src/layui/layui/layui.pro | 4 - 11 files changed, 331 insertions(+), 55 deletions(-) rename src/{layui/layui => laybasic/laybasic}/layEditorOptionsPage.cc (86%) rename src/{layui/layui => laybasic/laybasic}/layEditorOptionsPage.h (93%) rename src/{layui/layui => laybasic/laybasic}/layEditorOptionsPages.cc (90%) rename src/{layui/layui => laybasic/laybasic}/layEditorOptionsPages.h (96%) diff --git a/src/laybasic/laybasic/gsiDeclLayPlugin.cc b/src/laybasic/laybasic/gsiDeclLayPlugin.cc index 157b7366c..6fea78df1 100644 --- a/src/laybasic/laybasic/gsiDeclLayPlugin.cc +++ b/src/laybasic/laybasic/gsiDeclLayPlugin.cc @@ -24,38 +24,180 @@ #include "gsiDecl.h" #include "gsiDeclBasic.h" #include "layPlugin.h" +#include "layPluginConfigPage.h" +#include "layEditorOptionsPage.h" +#include "layEditorOptionsPages.h" #include "layViewObject.h" #include "layLayoutViewBase.h" #include "layCursor.h" namespace gsi { - class PluginFactoryBase; - class PluginBase; -// TODO: these static variables are a bad hack! -// However it's not easy to pass parameters to a C++ classes constructor in Ruby without -// compromising the capability to derive from that class (at least I have not learned how -// to create a "new" in the super class *and* allow a "new" of the derived class). Anyway, -// since PluginBase object are only allowed to be created inside the create_plugin method -// of the factory, this hack is a quick but dirty workaround. +class PluginFactoryBase; +class PluginBase; + +#if defined(HAVE_QTBINDINGS) +class EditorOptionsPageImpl + : public lay::EditorOptionsPage +{ +public: + EditorOptionsPageImpl (const std::string &title, int index) + : lay::EditorOptionsPage (), m_title (title), m_index (index) + { + // .. nothing yet .. + } + + virtual std::string title () const + { + return m_title; + } + + virtual int order () const + { + return m_index; + } + + void apply_impl (lay::Dispatcher *root) + { + lay::EditorOptionsPage::apply (root); + } + + virtual void apply (lay::Dispatcher *root) + { + if (f_apply.can_issue ()) { + f_apply.issue (&EditorOptionsPageImpl::apply_impl, root); + } else { + EditorOptionsPageImpl::apply_impl (root); + } + } + + void setup_impl (lay::Dispatcher *root) + { + lay::EditorOptionsPage::setup (root); + } + + virtual void setup (lay::Dispatcher *root) + { + if (f_setup.can_issue ()) { + f_setup.issue (&EditorOptionsPageImpl::setup_impl, root); + } else { + EditorOptionsPageImpl::setup_impl (root); + } + } + + gsi::Callback f_apply; + gsi::Callback f_setup; + +private: + tl::weak_ptr mp_view; + tl::weak_ptr mp_dispatcher; + std::string m_title; + int m_index; +}; + +EditorOptionsPageImpl *new_editor_options_page (const std::string &title, int index) +{ + return new EditorOptionsPageImpl (title, index); +} + +// @@@ methods: +// constructor new_editor_options_page +// view() +// edited() +// callback apply(dispatcher) +// callback setup(dispatcher) +// base: QWidget + +class ConfigPageImpl + : public lay::ConfigPage +{ +public: + ConfigPageImpl (const std::string &title) + : lay::ConfigPage (0), m_title (title) + { + // .. nothing yet .. + } + + virtual std::string title () const + { + return m_title; + } + + void commit_impl (lay::Dispatcher *root) + { + lay::ConfigPage::commit (root); + } + + virtual void commit (lay::Dispatcher *root) + { + if (f_commit.can_issue ()) { + f_commit.issue (&ConfigPageImpl::commit_impl, root); + } else { + ConfigPageImpl::commit_impl (root); + } + } + + void setup_impl (lay::Dispatcher *root) + { + lay::ConfigPage::setup (root); + } + + virtual void setup (lay::Dispatcher *root) + { + if (f_setup.can_issue ()) { + f_setup.issue (&ConfigPageImpl::setup_impl, root); + } else { + ConfigPageImpl::setup_impl (root); + } + } + + gsi::Callback f_commit; + gsi::Callback f_setup; + +private: + tl::weak_ptr mp_view; + tl::weak_ptr mp_dispatcher; + std::string m_title; + std::string m_index; +}; + +ConfigPageImpl *new_config_page (const std::string &title) +{ + return new ConfigPageImpl (title); +} + +// @@@ methods: +// constructor new_config_page +// callback apply(dispatcher) = commit +// callback setup(dispatcher) +// base: QFrame +#endif + +// HACK: used to track if we're inside a create_plugin method and can be sure that "init" is called static bool s_in_create_plugin = false; -static lay::LayoutViewBase *sp_view = 0; -static lay::Dispatcher *sp_dispatcher = 0; class PluginBase : public lay::Plugin, public lay::ViewService { public: PluginBase () - : lay::Plugin (sp_dispatcher), lay::ViewService (sp_view ? sp_view->canvas () : 0), - mp_view (sp_view), mp_dispatcher (sp_dispatcher) + : lay::Plugin (), lay::ViewService (), + mp_view (0), mp_dispatcher (0) { if (! s_in_create_plugin) { throw tl::Exception (tl::to_string (tr ("A PluginBase object can only be created in the PluginFactory's create_plugin method"))); } } + void init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) + { + mp_view = view; + mp_dispatcher = dispatcher; + lay::Plugin::init (dispatcher); + lay::ViewService::init (view ? view->canvas () : 0); + } + void grab_mouse () { if (ui ()) { @@ -282,6 +424,18 @@ public: return mp_dispatcher.get (); } +#if defined(HAVE_QTBINDINGS) + std::vector editor_option_pages () + { + lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages (); + if (!eo_pages) { + return std::vector (); + } else { + return eo_pages->pages (); + } + } +#endif + gsi::Callback f_menu_activated; gsi::Callback f_configure; gsi::Callback f_config_finalize; @@ -416,8 +570,79 @@ public: } } +#if defined(HAVE_QTBINDINGS) + std::vector get_editor_options_pages_impl () const + { + return std::vector (); + } + + virtual void get_editor_options_pages (std::vector &pages_out, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) const + { + try { + + std::vector pages; + if (f_get_editor_options_pages.can_issue ()) { + pages = f_get_editor_options_pages.issue > (&PluginFactoryBase::get_editor_options_pages_impl); + } else { + pages = get_editor_options_pages_impl (); + } + + pages_out.clear (); + for (auto i = pages.begin (); i != pages.end (); ++i) { + if (*i) { + (*i)->init (view, dispatcher); + pages_out.push_back (*i); + } + } + + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); + } catch (...) { + } + } + + std::vector get_config_pages_impl () const + { + return std::vector (); + } + + virtual std::vector > config_pages (QWidget *parent) const + { + std::vector > pages_out; + + try { + + std::vector pages; + + if (f_config_pages.can_issue ()) { + pages = f_config_pages.issue > (&PluginFactoryBase::get_config_pages_impl); + } else { + pages = get_config_pages_impl (); + } + + pages_out.clear (); + for (auto i = pages.begin (); i != pages.end (); ++i) { + if (*i) { + (*i)->setParent (parent); + pages_out.push_back (std::make_pair ((*i)->title (), *i)); + } + } + + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); + } catch (...) { + } + + return pages_out; + } +#endif + virtual lay::Plugin *create_plugin (db::Manager *manager, lay::Dispatcher *root, lay::LayoutViewBase *view) const - { + { if (f_create_plugin.can_issue ()) { return create_plugin_gsi (manager, root, view); } else { @@ -427,22 +652,25 @@ public: virtual gsi::PluginBase *create_plugin_gsi (db::Manager *manager, lay::Dispatcher *root, lay::LayoutViewBase *view) const { - // TODO: this is a hack. See notes above at s_in_create_plugin s_in_create_plugin = true; - sp_view = view; - sp_dispatcher = root; + gsi::PluginBase *ret = 0; try { + ret = f_create_plugin.issue (&PluginFactoryBase::create_plugin_gsi, manager, root, view); - s_in_create_plugin = false; - sp_view = 0; - sp_dispatcher = 0; + if (ret) { + ret->init (view, root); + } + + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); } catch (...) { - s_in_create_plugin = false; - sp_view = 0; - sp_dispatcher = 0; } + s_in_create_plugin = false; + return ret; } @@ -512,6 +740,8 @@ public: gsi::Callback f_configure; gsi::Callback f_config_finalize; gsi::Callback f_menu_activated; + gsi::Callback f_get_editor_options_pages; + gsi::Callback f_config_pages; private: std::vector > m_options; @@ -521,6 +751,12 @@ private: tl::RegisteredClass *mp_registration; }; +// @@@ +#if defined(HAVE_QTBINDINGS) +// get_editor_options_pages -> "create_editor_option_pages" +// config_pages -> "create_config_pages" +#endif + Class decl_PluginFactory ("lay", "PluginFactory", method ("register", &PluginFactoryBase::register_gsi, gsi::arg ("position"), gsi::arg ("name"), gsi::arg ("title"), "@brief Registers the plugin factory\n" diff --git a/src/layui/layui/layEditorOptionsPage.cc b/src/laybasic/laybasic/layEditorOptionsPage.cc similarity index 86% rename from src/layui/layui/layEditorOptionsPage.cc rename to src/laybasic/laybasic/layEditorOptionsPage.cc index 2da105f86..3f6a3046c 100644 --- a/src/layui/layui/layEditorOptionsPage.cc +++ b/src/laybasic/laybasic/layEditorOptionsPage.cc @@ -39,6 +39,20 @@ EditorOptionsPage::EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher attach_events (); } +EditorOptionsPage::EditorOptionsPage () + : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (0), mp_view (0) +{ + // .. nothing here -> call init to set view and dispatcher +} + +void +EditorOptionsPage::init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) +{ + mp_view = view; + mp_dispatcher = dispatcher; + attach_events (); +} + EditorOptionsPage::~EditorOptionsPage () { set_owner (0); diff --git a/src/layui/layui/layEditorOptionsPage.h b/src/laybasic/laybasic/layEditorOptionsPage.h similarity index 93% rename from src/layui/layui/layEditorOptionsPage.h rename to src/laybasic/laybasic/layEditorOptionsPage.h index 08598784e..9bbfae510 100644 --- a/src/layui/layui/layEditorOptionsPage.h +++ b/src/laybasic/laybasic/layEditorOptionsPage.h @@ -25,7 +25,7 @@ #ifndef HDR_layEditorOptionsPage #define HDR_layEditorOptionsPage -#include "layuiCommon.h" +#include "laybasicCommon.h" #include "tlObject.h" @@ -44,13 +44,14 @@ class EditorOptionsPages; /** * @brief The base class for a object properties page */ -class LAYUI_PUBLIC EditorOptionsPage +class LAYBASIC_PUBLIC EditorOptionsPage : public QWidget, public tl::Object { Q_OBJECT public: EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher); + EditorOptionsPage (); virtual ~EditorOptionsPage (); virtual std::string title () const = 0; @@ -66,13 +67,8 @@ public: const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; } void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; } -protected slots: - void edited () - { - apply (dispatcher ()); - } + void init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher); -protected: lay::Dispatcher *dispatcher () const { return mp_dispatcher; @@ -83,6 +79,13 @@ protected: return mp_view; } +protected slots: + void edited () + { + apply (dispatcher ()); + } + +protected: virtual void active_cellview_changed () { } virtual void technology_changed (const std::string & /*tech*/) { } diff --git a/src/layui/layui/layEditorOptionsPages.cc b/src/laybasic/laybasic/layEditorOptionsPages.cc similarity index 90% rename from src/layui/layui/layEditorOptionsPages.cc rename to src/laybasic/laybasic/layEditorOptionsPages.cc index 1a154d029..9daad1b5a 100644 --- a/src/layui/layui/layEditorOptionsPages.cc +++ b/src/laybasic/laybasic/layEditorOptionsPages.cc @@ -27,7 +27,6 @@ #include "tlExceptions.h" #include "layPlugin.h" #include "layLayoutViewBase.h" -#include "layQtTools.h" #include #include @@ -197,22 +196,6 @@ BEGIN_PROTECTED END_PROTECTED_W (this) } -// ------------------------------------------------------------------ -// Indicates an error on a line edit - -template -static void configure_from_line_edit (lay::Dispatcher *dispatcher, QLineEdit *le, const std::string &cfg_name) -{ - try { - Value value = Value (0); - tl::from_string_ext (tl::to_string (le->text ()), value); - dispatcher->config_set (cfg_name, tl::to_string (value)); - lay::indicate_error (le, (tl::Exception *) 0); - } catch (tl::Exception &ex) { - lay::indicate_error (le, &ex); - } -} - } #endif diff --git a/src/layui/layui/layEditorOptionsPages.h b/src/laybasic/laybasic/layEditorOptionsPages.h similarity index 96% rename from src/layui/layui/layEditorOptionsPages.h rename to src/laybasic/laybasic/layEditorOptionsPages.h index 07c172e6b..1cd66753c 100644 --- a/src/layui/layui/layEditorOptionsPages.h +++ b/src/laybasic/laybasic/layEditorOptionsPages.h @@ -25,7 +25,7 @@ #ifndef HDR_layEditorOptionsPages #define HDR_layEditorOptionsPages -#include "layuiCommon.h" +#include "laybasicCommon.h" #include "layEditorOptionsPage.h" #include @@ -47,7 +47,7 @@ class Plugin; /** * @brief The object properties dialog */ -class LAYUI_PUBLIC EditorOptionsPages +class LAYBASIC_PUBLIC EditorOptionsPages : public QFrame { Q_OBJECT diff --git a/src/laybasic/laybasic/layPlugin.cc b/src/laybasic/laybasic/layPlugin.cc index 6965283d5..0184e2f6b 100644 --- a/src/laybasic/laybasic/layPlugin.cc +++ b/src/laybasic/laybasic/layPlugin.cc @@ -308,8 +308,23 @@ PluginDeclaration::register_plugin () // Plugin implementation Plugin::Plugin (Plugin *parent, bool standalone) - : mp_parent (parent), mp_plugin_declaration (0), dm_finalize_config (this, &lay::Plugin::config_end), m_standalone (standalone) + : mp_parent (0), mp_plugin_declaration (0), dm_finalize_config (this, &lay::Plugin::config_end), m_standalone (false) { + init (parent, standalone); +} + +Plugin::Plugin () + : mp_parent (0), mp_plugin_declaration (0), dm_finalize_config (this, &lay::Plugin::config_end), m_standalone (false) +{ + // .. nothing yet (waiting for init) .. +} + +void +Plugin::init (Plugin *parent, bool standalone) +{ + mp_parent = parent; + m_standalone = standalone; + if (! parent) { if (! standalone) { // load the root with the default configuration @@ -324,6 +339,7 @@ Plugin::Plugin (Plugin *parent, bool standalone) } } + Plugin::~Plugin () { if (mp_parent) { diff --git a/src/laybasic/laybasic/layPlugin.h b/src/laybasic/laybasic/layPlugin.h index 989bd233b..f334252cd 100644 --- a/src/laybasic/laybasic/layPlugin.h +++ b/src/laybasic/laybasic/layPlugin.h @@ -504,6 +504,18 @@ public: */ Plugin (Plugin *parent, bool standalone = false); + /** + * @brief The default constructor + * + * This constructor needs to be followed by init() + */ + Plugin (); + + /** + * @brief Initialization, following the default constructor + */ + void init (Plugin *parent, bool standalone = false); + /** * @brief The destructor */ diff --git a/src/laybasic/laybasic/layViewObject.cc b/src/laybasic/laybasic/layViewObject.cc index fe9329fcd..3cfa61c04 100644 --- a/src/laybasic/laybasic/layViewObject.cc +++ b/src/laybasic/laybasic/layViewObject.cc @@ -191,8 +191,15 @@ ViewObject::freeze () // ViewService implementation ViewService::ViewService (ViewObjectUI *widget) - : mp_widget (widget), m_abs_grab (false), m_enabled (true) + : mp_widget (0), m_abs_grab (false), m_enabled (true) { + init (widget); +} + +void +ViewService::init (ViewObjectUI *widget) +{ + mp_widget = widget; if (widget) { widget->register_service (this); } diff --git a/src/laybasic/laybasic/layViewObject.h b/src/laybasic/laybasic/layViewObject.h index 889eae89b..7664b8f78 100644 --- a/src/laybasic/laybasic/layViewObject.h +++ b/src/laybasic/laybasic/layViewObject.h @@ -104,6 +104,11 @@ public: */ ViewService (ViewObjectUI *widget = 0); + /** + * @brief Initialization, can follow default constructor + */ + void init (ViewObjectUI *widget); + /** * @brief Destructor */ diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index 4262ca687..293b456b7 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -35,6 +35,8 @@ SOURCES += \ gsiDeclLayTlAdded.cc \ gsiDeclLayRdbAdded.cc \ layAbstractMenu.cc \ + layEditorOptionsPage.cc \ + layEditorOptionsPages.cc \ layLayoutViewConfig.cc \ layMargin.cc \ laybasicForceLink.cc \ @@ -87,6 +89,8 @@ SOURCES += \ layUtils.cc \ HEADERS += \ + layEditorOptionsPage.h \ + layEditorOptionsPages.h \ layMargin.h \ laybasicConfig.h \ laybasicForceLink.h \ diff --git a/src/layui/layui/layui.pro b/src/layui/layui/layui.pro index 094e58410..cf30329d0 100644 --- a/src/layui/layui/layui.pro +++ b/src/layui/layui/layui.pro @@ -104,8 +104,6 @@ SOURCES = \ layEditStippleWidget.cc \ layEditStipplesForm.cc \ layEditorOptionsFrame.cc \ - layEditorOptionsPage.cc \ - layEditorOptionsPages.cc \ layFileDialog.cc \ layGenericSyntaxHighlighter.cc \ layHierarchyControlPanel.cc \ @@ -164,8 +162,6 @@ HEADERS = \ layEditStippleWidget.h \ layEditStipplesForm.h \ layEditorOptionsFrame.h \ - layEditorOptionsPage.h \ - layEditorOptionsPages.h \ layFileDialog.h \ layGenericSyntaxHighlighter.h \ layHierarchyControlPanel.h \