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
{
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)
: 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<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"),
"@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<EditorOptionsPageImpl> 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"
);

View File

@ -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> (&lay::EditorServiceBase::activated);
} else {
lay::EditorServiceBase::activated ();
f_activated.issue<PluginImpl> (&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<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
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);
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<lay::Dispatcher *> (mp_dispatcher.get ());
}
#if defined(HAVE_QTBINDINGS)
std::vector<QWidget *> editor_options_pages ();
#endif
gsi::Callback f_menu_activated;
gsi::Callback f_configure;
gsi::Callback f_config_finalize;

View File

@ -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 ()
{

View File

@ -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;

View File

@ -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 {

View File

@ -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 <lay::EditorOptionsPage *> &pages () const
{

View File

@ -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<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

View File

@ -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<lay::EditorOptionsPage *> 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;
};
}