From 1e570351fbcc7ef0fdfdd0eec640557e0de09b00 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 31 Aug 2025 20:37:48 +0200 Subject: [PATCH] Refactoring (GSI base class for EditorOptionsPage), preparations for 'focus_page' feature --- src/lay/lay/gsiDeclLayEditorOptionsPage.cc | 53 +++++++++++++++++-- src/lay/lay/gsiDeclLayPlugin.cc | 32 ++++------- src/lay/lay/gsiDeclLayPlugin.h | 5 +- src/laybasic/laybasic/layEditorOptionsPage.cc | 12 ++++- src/laybasic/laybasic/layEditorOptionsPage.h | 5 ++ .../laybasic/layEditorOptionsPages.cc | 13 ++++- src/laybasic/laybasic/layEditorOptionsPages.h | 1 + src/laybasic/laybasic/layEditorServiceBase.cc | 50 ++++++++++++++++- src/laybasic/laybasic/layEditorServiceBase.h | 26 ++++++--- 9 files changed, 154 insertions(+), 43 deletions(-) diff --git a/src/lay/lay/gsiDeclLayEditorOptionsPage.cc b/src/lay/lay/gsiDeclLayEditorOptionsPage.cc index 318aa1385..b5860e3ef 100644 --- a/src/lay/lay/gsiDeclLayEditorOptionsPage.cc +++ b/src/lay/lay/gsiDeclLayEditorOptionsPage.cc @@ -30,6 +30,51 @@ namespace gsi { +Class decl_EditorOptionsPageBase (QT_EXTERNAL_BASE (QWidget) "lay", "EditorOptionsPageBase", + method ("view", &lay::EditorOptionsPage::view, + "@brief Gets the view object this page is associated with\n" + ) + + method ("title", &lay::EditorOptionsPage::title, + "@brief Gets the title string of the page\n" + ) + + method ("order", &lay::EditorOptionsPage::order, + "@brief Gets the order index of the page\n" + ) + + method ("is_focus_page?", &lay::EditorOptionsPage::is_focus_page, + "@brief Gets a flag indicating whether the page is a focus page\n" + "See \\focus_page= for a description is this attribute.\n" + ) + + method ("focus_page=", &lay::EditorOptionsPage::set_focus_page, gsi::arg ("flag"), + "@brief Sets a flag indicating whether the page is a focus page\n" + "The focus page is the page that is selected when the tab key is pressed during some plugin action.\n" + ) + + method ("make_current", &lay::EditorOptionsPage::make_current, + "@brief Brings the page to the front of the tab stack\n" + "Calling this method will make this page the current one in the tab stack, provided " + "the page is visible." + ) + + method ("do_apply", &lay::EditorOptionsPage::apply, gsi::arg ("dispatcher"), + "@brief Transfers data from the page to the configuration\n" + "Calling this method will call the actual 'apply' implementation which is " + "provided by a reimplementation - either on C++ or script side." + ) + + method ("do_setup", &lay::EditorOptionsPage::setup, gsi::arg ("dispatcher"), + "@brief Transfers data from the configuration to the page\n" + "Calling this method will call the actual 'setup' implementation which is " + "provided by a reimplementation - either on C++ or script side." + ), + "@brief The plugin framework's editor options page base class\n" + "\n" + "This class is provided as an interface to the base class implementation for various functions.\n" + "You can use these methods in order to pass down events to the original implementation or access\n" + "objects not created in script space.\n" + "\n" + "It features some useful methods such as 'view' and provides a slot to call for triggering a data " + "transfer ('edited').\n" + "\n" + "This class has been introduced in version 0.30.4.\n" +); + EditorOptionsPageImpl::EditorOptionsPageImpl (const std::string &title, int index) : lay::EditorOptionsPage (), m_title (title), m_index (index) { @@ -79,15 +124,12 @@ EditorOptionsPageImpl *new_editor_options_page (const std::string &title, int in return new EditorOptionsPageImpl (title, index); } -Class decl_EditorOptionsPage (QT_EXTERNAL_BASE (QWidget) "lay", "EditorOptionsPage", +Class decl_EditorOptionsPage (decl_EditorOptionsPageBase, "lay", "EditorOptionsPage", constructor ("new", &new_editor_options_page, gsi::arg ("title"), gsi::arg ("index"), "@brief Creates a new EditorOptionsPage object\n" "@param title The title of the page\n" "@param index The position of the page in the tab bar\n" ) + - method ("view", &EditorOptionsPageImpl::view, - "@brief Gets the view object this page is associated with\n" - ) + method ("edited", &EditorOptionsPageImpl::call_edited, "@brief Call this method when some entry widget has changed\n" "When some entry widget (for example 'editingFinished' slot of a QLineEdit), " @@ -117,6 +159,9 @@ Class decl_EditorOptionsPage (QT_EXTERNAL_BASE (QWidget) "configuration parameters into editor widget states. Both methods are called by the system when " "some transfer is needed.\n" "\n" + "When you want to respond to widget signals and transfer information, call \\edited " + "in the signal slot. This will trigger a transfer (aka 'apply').\n" + "\n" "This class has been introduced in version 0.30.4.\n" ); diff --git a/src/lay/lay/gsiDeclLayPlugin.cc b/src/lay/lay/gsiDeclLayPlugin.cc index 9b40b42c3..1d055a537 100644 --- a/src/lay/lay/gsiDeclLayPlugin.cc +++ b/src/lay/lay/gsiDeclLayPlugin.cc @@ -507,15 +507,20 @@ PluginImpl::wheel_event_noref (int delta, bool horizontal, db::DPoint p, unsigne } void -PluginImpl::activated () +PluginImpl::activated_impl () { if (f_activated.can_issue ()) { - f_activated.issue (&lay::EditorServiceBase::activated); - } else { - lay::EditorServiceBase::activated (); + f_activated.issue (&PluginImpl::activated_impl); } } +void +PluginImpl::activated () +{ + lay::EditorServiceBase::activated (); + activated_impl (); +} + void PluginImpl::deactivated_impl () { @@ -641,25 +646,6 @@ PluginImpl::tracking_position () const } } -#if defined(HAVE_QTBINDINGS) -std::vector -PluginImpl::editor_options_pages () -{ - lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages (); - if (!eo_pages) { - return std::vector (); - } else { - std::vector pages; - for (auto p = eo_pages->pages ().begin (); p != eo_pages->pages ().end (); ++p) { - if ((*p)->plugin_declaration () == plugin_declaration ()) { - pages.push_back (*p); - } - } - return pages; - } -} -#endif - lay::angle_constraint_type PluginImpl::connect_ac (lay::angle_constraint_type ac) const { diff --git a/src/lay/lay/gsiDeclLayPlugin.h b/src/lay/lay/gsiDeclLayPlugin.h index fa639e518..52bd3b448 100644 --- a/src/lay/lay/gsiDeclLayPlugin.h +++ b/src/lay/lay/gsiDeclLayPlugin.h @@ -76,6 +76,7 @@ public: bool mouse_release_event_noref (db::DPoint p, unsigned int buttons, bool prio); virtual bool wheel_event (int delta, bool horizontal, const db::DPoint &p, unsigned int buttons, bool prio); bool wheel_event_noref (int delta, bool horizontal, db::DPoint p, unsigned int buttons, bool prio); + void activated_impl (); virtual void activated (); void deactivated_impl (); virtual void deactivated (); @@ -109,10 +110,6 @@ public: return const_cast (mp_dispatcher.get ()); } -#if defined(HAVE_QTBINDINGS) - std::vector editor_options_pages (); -#endif - gsi::Callback f_menu_activated; gsi::Callback f_configure; gsi::Callback f_config_finalize; diff --git a/src/laybasic/laybasic/layEditorOptionsPage.cc b/src/laybasic/laybasic/layEditorOptionsPage.cc index 3f6a3046c..7ef7ded95 100644 --- a/src/laybasic/laybasic/layEditorOptionsPage.cc +++ b/src/laybasic/laybasic/layEditorOptionsPage.cc @@ -34,13 +34,13 @@ namespace lay // EditorOptionsPage implementation EditorOptionsPage::EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) - : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher), mp_view (view) + : QWidget (0), mp_owner (0), m_active (true), m_focus_page (false), mp_plugin_declaration (0), mp_dispatcher (dispatcher), mp_view (view) { attach_events (); } EditorOptionsPage::EditorOptionsPage () - : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (0), mp_view (0) + : QWidget (0), mp_owner (0), m_active (true), m_focus_page (false), mp_plugin_declaration (0), mp_dispatcher (0), mp_view (0) { // .. nothing here -> call init to set view and dispatcher } @@ -58,6 +58,14 @@ EditorOptionsPage::~EditorOptionsPage () set_owner (0); } +void +EditorOptionsPage::make_current () +{ + if (mp_owner && m_active) { + mp_owner->make_page_current (this); + } +} + void EditorOptionsPage::attach_events () { diff --git a/src/laybasic/laybasic/layEditorOptionsPage.h b/src/laybasic/laybasic/layEditorOptionsPage.h index 9bbfae510..298cbc183 100644 --- a/src/laybasic/laybasic/layEditorOptionsPage.h +++ b/src/laybasic/laybasic/layEditorOptionsPage.h @@ -60,10 +60,14 @@ public: virtual void setup (lay::Dispatcher * /*root*/) { } virtual void commit_recent (lay::Dispatcher * /*root*/) { } + bool is_focus_page () const { return m_focus_page; } + void set_focus_page (bool f) { m_focus_page = f; } bool active () const { return m_active; } void activate (bool active); void set_owner (EditorOptionsPages *owner); + void make_current (); + const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; } void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; } @@ -92,6 +96,7 @@ protected: private: EditorOptionsPages *mp_owner; bool m_active; + bool m_focus_page; const lay::PluginDeclaration *mp_plugin_declaration; lay::Dispatcher *mp_dispatcher; lay::LayoutViewBase *mp_view; diff --git a/src/laybasic/laybasic/layEditorOptionsPages.cc b/src/laybasic/laybasic/layEditorOptionsPages.cc index eefe25ee9..738528d27 100644 --- a/src/laybasic/laybasic/layEditorOptionsPages.cc +++ b/src/laybasic/laybasic/layEditorOptionsPages.cc @@ -120,7 +120,18 @@ EditorOptionsPages::unregister_page (lay::EditorOptionsPage *page) update (0); } -void +void +EditorOptionsPages::make_page_current (lay::EditorOptionsPage *page) +{ + for (int i = 0; i < mp_pages->count (); ++i) { + if (mp_pages->widget (i) == page) { + mp_pages->setCurrentIndex (i); + break; + } + } +} + +void EditorOptionsPages::activate_page (lay::EditorOptionsPage *page) { try { diff --git a/src/laybasic/laybasic/layEditorOptionsPages.h b/src/laybasic/laybasic/layEditorOptionsPages.h index dd4e1b15c..10024e982 100644 --- a/src/laybasic/laybasic/layEditorOptionsPages.h +++ b/src/laybasic/laybasic/layEditorOptionsPages.h @@ -60,6 +60,7 @@ public: void activate_page (lay::EditorOptionsPage *page); void activate (const lay::Plugin *plugin); void focusInEvent (QFocusEvent *event); + void make_page_current (lay::EditorOptionsPage *page); const std::vector &pages () const { diff --git a/src/laybasic/laybasic/layEditorServiceBase.cc b/src/laybasic/laybasic/layEditorServiceBase.cc index 1a3e4c86c..e20f200a5 100644 --- a/src/laybasic/laybasic/layEditorServiceBase.cc +++ b/src/laybasic/laybasic/layEditorServiceBase.cc @@ -21,6 +21,8 @@ */ #include "layEditorServiceBase.h" +#include "layEditorOptionsPage.h" +#include "layEditorOptionsPages.h" #include "layViewport.h" #include "layLayoutViewBase.h" #include "laybasicConfig.h" @@ -212,7 +214,8 @@ EditorServiceBase::EditorServiceBase (LayoutViewBase *view) lay::Plugin (view), mp_view (view), m_cursor_enabled (true), - m_has_tracking_position (false) + m_has_tracking_position (false), + m_active (false) { // .. nothing yet .. } @@ -328,6 +331,51 @@ void EditorServiceBase::deactivated () { clear_mouse_cursors (); + m_active = false; +} + +void +EditorServiceBase::activated () +{ + m_active = true; +} + +#if defined(HAVE_QT) +std::vector +EditorServiceBase::editor_options_pages () +{ + lay::EditorOptionsPages *eo_pages = mp_view->editor_options_pages (); + if (!eo_pages) { + return std::vector (); + } else { + std::vector pages; + for (auto p = eo_pages->pages ().begin (); p != eo_pages->pages ().end (); ++p) { + if ((*p)->plugin_declaration () == plugin_declaration ()) { + pages.push_back (*p); + } + } + return pages; + } +} +#endif + +bool +EditorServiceBase::key_event (unsigned int key, unsigned int buttons) +{ +#if defined(HAVE_QT) + if (is_active () && key == Qt::Key_Tab && buttons == 0) { + auto pages = editor_options_pages (); + for (auto p = pages.begin (); p != pages.end (); ++p) { + if ((*p)->is_focus_page ()) { + (*p)->make_current (); + (*p)->setFocus (Qt::TabFocusReason); + return true; + } + } + } +#endif + + return false; } void diff --git a/src/laybasic/laybasic/layEditorServiceBase.h b/src/laybasic/laybasic/layEditorServiceBase.h index 7a73c8bb8..1c50bebbc 100644 --- a/src/laybasic/laybasic/layEditorServiceBase.h +++ b/src/laybasic/laybasic/layEditorServiceBase.h @@ -74,6 +74,14 @@ public: return this; } + /** + * @brief Gets a value indicating whether the plugin is active + */ + bool is_active () const + { + return m_active; + } + /** * @brief Adds a mouse cursor to the given point */ @@ -170,18 +178,12 @@ public: /** * @brief Called when the plugin is activated */ - virtual void activated () - { - // .. this implementation does nothing .. - } + virtual void activated (); /** * @brief Key event handler */ - virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/) - { - return false; - } + virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/); /** * @brief Mouse press event handler @@ -263,6 +265,13 @@ public: // The default implementation does nothing } +#if defined(HAVE_QT) + /** + * @brief Gets the editor options pages associated with this plugin + */ + std::vector editor_options_pages (); +#endif + private: // The marker representing the mouse cursor lay::LayoutViewBase *mp_view; @@ -271,6 +280,7 @@ private: bool m_cursor_enabled; bool m_has_tracking_position; db::DPoint m_tracking_position; + bool m_active; }; }