Refactoring (GSI base class for EditorOptionsPage), preparations for 'focus_page' feature

This commit is contained in:
Matthias Koefferlein 2025-08-31 20:37:48 +02:00
parent e21eb6aafc
commit 1e570351fb
9 changed files with 154 additions and 43 deletions

View File

@ -30,6 +30,51 @@
namespace gsi namespace gsi
{ {
Class<lay::EditorOptionsPage> 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) EditorOptionsPageImpl::EditorOptionsPageImpl (const std::string &title, int index)
: lay::EditorOptionsPage (), m_title (title), m_index (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); return new EditorOptionsPageImpl (title, index);
} }
Class<EditorOptionsPageImpl> decl_EditorOptionsPage (QT_EXTERNAL_BASE (QWidget) "lay", "EditorOptionsPage", Class<EditorOptionsPageImpl> decl_EditorOptionsPage (decl_EditorOptionsPageBase, "lay", "EditorOptionsPage",
constructor ("new", &new_editor_options_page, gsi::arg ("title"), gsi::arg ("index"), constructor ("new", &new_editor_options_page, gsi::arg ("title"), gsi::arg ("index"),
"@brief Creates a new EditorOptionsPage object\n" "@brief Creates a new EditorOptionsPage object\n"
"@param title The title of the page\n" "@param title The title of the page\n"
"@param index The position of the page in the tab bar\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, method ("edited", &EditorOptionsPageImpl::call_edited,
"@brief Call this method when some entry widget has changed\n" "@brief Call this method when some entry widget has changed\n"
"When some entry widget (for example 'editingFinished' slot of a QLineEdit), " "When some entry widget (for example 'editingFinished' slot of a QLineEdit), "
@ -117,6 +159,9 @@ Class<EditorOptionsPageImpl> decl_EditorOptionsPage (QT_EXTERNAL_BASE (QWidget)
"configuration parameters into editor widget states. Both methods are called by the system when " "configuration parameters into editor widget states. Both methods are called by the system when "
"some transfer is needed.\n" "some transfer is needed.\n"
"\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" "This class has been introduced in version 0.30.4.\n"
); );

View File

@ -507,15 +507,20 @@ PluginImpl::wheel_event_noref (int delta, bool horizontal, db::DPoint p, unsigne
} }
void void
PluginImpl::activated () PluginImpl::activated_impl ()
{ {
if (f_activated.can_issue ()) { if (f_activated.can_issue ()) {
f_activated.issue<lay::EditorServiceBase> (&lay::EditorServiceBase::activated); f_activated.issue<PluginImpl> (&PluginImpl::activated_impl);
} else {
lay::EditorServiceBase::activated ();
} }
} }
void
PluginImpl::activated ()
{
lay::EditorServiceBase::activated ();
activated_impl ();
}
void void
PluginImpl::deactivated_impl () PluginImpl::deactivated_impl ()
{ {
@ -641,25 +646,6 @@ PluginImpl::tracking_position () const
} }
} }
#if defined(HAVE_QTBINDINGS)
std::vector<QWidget *>
PluginImpl::editor_options_pages ()
{
lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages ();
if (!eo_pages) {
return std::vector<QWidget *> ();
} else {
std::vector<QWidget *> 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 lay::angle_constraint_type
PluginImpl::connect_ac (lay::angle_constraint_type ac) const PluginImpl::connect_ac (lay::angle_constraint_type ac) const
{ {

View File

@ -76,6 +76,7 @@ public:
bool mouse_release_event_noref (db::DPoint p, unsigned int buttons, bool prio); 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); 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); bool wheel_event_noref (int delta, bool horizontal, db::DPoint p, unsigned int buttons, bool prio);
void activated_impl ();
virtual void activated (); virtual void activated ();
void deactivated_impl (); void deactivated_impl ();
virtual void deactivated (); virtual void deactivated ();
@ -109,10 +110,6 @@ public:
return const_cast<lay::Dispatcher *> (mp_dispatcher.get ()); return const_cast<lay::Dispatcher *> (mp_dispatcher.get ());
} }
#if defined(HAVE_QTBINDINGS)
std::vector<QWidget *> editor_options_pages ();
#endif
gsi::Callback f_menu_activated; gsi::Callback f_menu_activated;
gsi::Callback f_configure; gsi::Callback f_configure;
gsi::Callback f_config_finalize; gsi::Callback f_config_finalize;

View File

@ -34,13 +34,13 @@ namespace lay
// EditorOptionsPage implementation // EditorOptionsPage implementation
EditorOptionsPage::EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) 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 (); attach_events ();
} }
EditorOptionsPage::EditorOptionsPage () 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 // .. nothing here -> call init to set view and dispatcher
} }
@ -58,6 +58,14 @@ EditorOptionsPage::~EditorOptionsPage ()
set_owner (0); set_owner (0);
} }
void
EditorOptionsPage::make_current ()
{
if (mp_owner && m_active) {
mp_owner->make_page_current (this);
}
}
void void
EditorOptionsPage::attach_events () EditorOptionsPage::attach_events ()
{ {

View File

@ -60,10 +60,14 @@ public:
virtual void setup (lay::Dispatcher * /*root*/) { } virtual void setup (lay::Dispatcher * /*root*/) { }
virtual void commit_recent (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; } bool active () const { return m_active; }
void activate (bool active); void activate (bool active);
void set_owner (EditorOptionsPages *owner); void set_owner (EditorOptionsPages *owner);
void make_current ();
const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; } const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; }
void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; } void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; }
@ -92,6 +96,7 @@ protected:
private: private:
EditorOptionsPages *mp_owner; EditorOptionsPages *mp_owner;
bool m_active; bool m_active;
bool m_focus_page;
const lay::PluginDeclaration *mp_plugin_declaration; const lay::PluginDeclaration *mp_plugin_declaration;
lay::Dispatcher *mp_dispatcher; lay::Dispatcher *mp_dispatcher;
lay::LayoutViewBase *mp_view; lay::LayoutViewBase *mp_view;

View File

@ -120,6 +120,17 @@ EditorOptionsPages::unregister_page (lay::EditorOptionsPage *page)
update (0); update (0);
} }
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 void
EditorOptionsPages::activate_page (lay::EditorOptionsPage *page) EditorOptionsPages::activate_page (lay::EditorOptionsPage *page)
{ {

View File

@ -60,6 +60,7 @@ public:
void activate_page (lay::EditorOptionsPage *page); void activate_page (lay::EditorOptionsPage *page);
void activate (const lay::Plugin *plugin); void activate (const lay::Plugin *plugin);
void focusInEvent (QFocusEvent *event); void focusInEvent (QFocusEvent *event);
void make_page_current (lay::EditorOptionsPage *page);
const std::vector <lay::EditorOptionsPage *> &pages () const const std::vector <lay::EditorOptionsPage *> &pages () const
{ {

View File

@ -21,6 +21,8 @@
*/ */
#include "layEditorServiceBase.h" #include "layEditorServiceBase.h"
#include "layEditorOptionsPage.h"
#include "layEditorOptionsPages.h"
#include "layViewport.h" #include "layViewport.h"
#include "layLayoutViewBase.h" #include "layLayoutViewBase.h"
#include "laybasicConfig.h" #include "laybasicConfig.h"
@ -212,7 +214,8 @@ EditorServiceBase::EditorServiceBase (LayoutViewBase *view)
lay::Plugin (view), lay::Plugin (view),
mp_view (view), mp_view (view),
m_cursor_enabled (true), m_cursor_enabled (true),
m_has_tracking_position (false) m_has_tracking_position (false),
m_active (false)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -328,6 +331,51 @@ void
EditorServiceBase::deactivated () EditorServiceBase::deactivated ()
{ {
clear_mouse_cursors (); clear_mouse_cursors ();
m_active = false;
}
void
EditorServiceBase::activated ()
{
m_active = true;
}
#if defined(HAVE_QT)
std::vector<lay::EditorOptionsPage *>
EditorServiceBase::editor_options_pages ()
{
lay::EditorOptionsPages *eo_pages = mp_view->editor_options_pages ();
if (!eo_pages) {
return std::vector<lay::EditorOptionsPage *> ();
} else {
std::vector<lay::EditorOptionsPage *> 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 void

View File

@ -74,6 +74,14 @@ public:
return this; 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 * @brief Adds a mouse cursor to the given point
*/ */
@ -170,18 +178,12 @@ public:
/** /**
* @brief Called when the plugin is activated * @brief Called when the plugin is activated
*/ */
virtual void activated () virtual void activated ();
{
// .. this implementation does nothing ..
}
/** /**
* @brief Key event handler * @brief Key event handler
*/ */
virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/) virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/);
{
return false;
}
/** /**
* @brief Mouse press event handler * @brief Mouse press event handler
@ -263,6 +265,13 @@ public:
// The default implementation does nothing // The default implementation does nothing
} }
#if defined(HAVE_QT)
/**
* @brief Gets the editor options pages associated with this plugin
*/
std::vector<lay::EditorOptionsPage *> editor_options_pages ();
#endif
private: private:
// The marker representing the mouse cursor // The marker representing the mouse cursor
lay::LayoutViewBase *mp_view; lay::LayoutViewBase *mp_view;
@ -271,6 +280,7 @@ private:
bool m_cursor_enabled; bool m_cursor_enabled;
bool m_has_tracking_position; bool m_has_tracking_position;
db::DPoint m_tracking_position; db::DPoint m_tracking_position;
bool m_active;
}; };
} }