Basically enabling AbstractMenu in non-Qt mode

As a way to trigger actions inside the layout view
and plugins.

Right now, the layout view's menu is only a rudimentary one
as it lacks the top-level menus usually provided by the main window.
This commit is contained in:
Matthias Koefferlein 2022-06-07 23:27:34 +02:00
parent ac5c66400d
commit 1020eb6e99
19 changed files with 361 additions and 168 deletions

View File

@ -24,10 +24,10 @@
#include "layPlugin.h"
#include "layConverters.h"
#include "layDispatcher.h"
#include "layAbstractMenu.h"
#include "tlColor.h"
#if defined(HAVE_QT)
# include "layConfigurationDialog.h"
# include "layAbstractMenu.h"
#endif
#include "antConfig.h"
#if defined(HAVE_QT)
@ -214,15 +214,12 @@ PluginDeclaration::initialized (lay::Dispatcher *root)
void
PluginDeclaration::uninitialize (lay::Dispatcher *)
{
#if defined(HAVE_QT)
m_actions.clear ();
#endif
}
void
PluginDeclaration::update_current_template ()
{
#if defined(HAVE_QT)
lay::Dispatcher *mp = lay::Dispatcher::instance ();
if (! mp || ! mp->has_ui ()) {
return;
@ -248,13 +245,11 @@ PluginDeclaration::update_current_template ()
}
}
#endif
}
void
PluginDeclaration::update_menu ()
{
#if defined(HAVE_QT)
lay::Dispatcher *mp = lay::Dispatcher::instance ();
if (! mp || ! mp->has_ui ()) {
return;
@ -294,7 +289,6 @@ PluginDeclaration::update_menu ()
}
}
}
#endif
}
void

View File

@ -64,9 +64,7 @@ private:
std::vector<ant::Template> m_templates;
int m_current_template;
#if defined(HAVE_QT)
tl::weak_collection<lay::ConfigureAction> m_actions;
#endif
bool m_current_template_updated;
bool m_templates_updated;
};

View File

@ -180,6 +180,7 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled)
m_manager (undo_enabled)
{
m_dispatcher.set_menu_parent_widget (this);
m_dispatcher.make_menu ();
// ensures the deferred method scheduler is present
tl::DeferredMethodScheduler::instance ();

View File

@ -461,6 +461,11 @@ static LayerPropertiesConstIteratorWrapper each_layer2 (lay::LayoutViewBase *vie
return LayerPropertiesConstIteratorWrapper (view->begin_layers (list_index));
}
static lay::AbstractMenu *menu (lay::LayoutViewBase *view)
{
return view->menu ();
}
#if defined(HAVE_QT)
LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase (QT_EXTERNAL_BASE (QWidget) "lay", "LayoutViewBase",
#else
@ -976,6 +981,14 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase (QT_EXTERNAL_BASE
"\n"
"This method has been introduced in version 0.28."
) +
gsi::method_ext ("menu", &menu,
"@brief Gets the \\AbstractMenu associated with this view.\n"
"\n"
"In normal UI application mode this is the main window's view. For a detached view or in non-UI "
"applications this is the view's private menu.\n"
"\n"
"This method has been introduced in version 0.28."
) +
gsi::method ("call_menu", &lay::LayoutViewBase::menu_activated, gsi::arg ("symbol"),
"@brief Calls the menu item with the provided symbol.\n"
"To obtain all symbols, use \\menu_symbols.\n"

View File

@ -20,8 +20,6 @@
*/
#if defined(HAVE_QT)
#include "gsiDecl.h"
#include "gsiSignals.h"
#include "layAbstractMenu.h"
@ -411,5 +409,3 @@ Class<ActionStub> decl_Action (decl_ActionBase, "lay", "Action",
);
}
#endif

View File

@ -20,8 +20,6 @@
*/
#if defined(HAVE_QT)
#include "layAbstractMenu.h"
#include "layDispatcher.h"
#include "layPlugin.h"
@ -30,17 +28,19 @@
#include "gtf.h"
#include "gsi.h"
#include <QAction>
#include <QActionGroup>
#include <QMenu>
#include <QMenuBar>
#include <QShortcutEvent>
#include <QToolBar>
#include <QToolButton>
#include <QApplication>
#include <QMessageBox>
#include <QHBoxLayout>
#include <QFrame>
#if defined(HAVE_QT)
# include <QAction>
# include <QActionGroup>
# include <QMenu>
# include <QMenuBar>
# include <QShortcutEvent>
# include <QToolBar>
# include <QToolButton>
# include <QApplication>
# include <QMessageBox>
# include <QHBoxLayout>
# include <QFrame>
#endif
#include <ctype.h>
@ -245,12 +245,14 @@ AbstractMenuItem::set_action (Action *a, bool copy_properties)
a->keep ();
#if defined(HAVE_QT)
if (copy_properties && mp_action->qaction () && a->qaction ()) {
a->qaction ()->setIcon (mp_action->qaction ()->icon ());
a->qaction ()->setToolTip (mp_action->qaction ()->toolTip ());
a->qaction ()->setShortcut (mp_action->qaction ()->shortcut ());
a->qaction ()->setIconText (mp_action->qaction ()->iconText ());
}
#endif
bool enabled = mp_action.get () ? mp_action->is_enabled () : true;
bool visible = mp_action.get () ? mp_action->is_visible () : true;
@ -261,9 +263,11 @@ AbstractMenuItem::set_action (Action *a, bool copy_properties)
mp_action->set_dispatcher (mp_dispatcher);
mp_action->set_object_name (m_basename);
#if defined(HAVE_QT)
if (mp_action->menu ()) {
mp_action->menu ()->setObjectName (tl::to_qstring (m_basename));
}
#endif
}
void
@ -289,30 +293,8 @@ AbstractMenuItem::set_remove_on_empty ()
static std::set<Action *> *sp_actionHandles = 0;
static void
configure_action_from_title (Action *ah, const std::string &s)
{
std::string title;
std::string shortcut;
std::string res;
std::string tool_tip;
parse_menu_title (s, title, shortcut, res, tool_tip);
ah->qaction ()->setText (tl::to_qstring (title));
if (! tool_tip.empty ()) {
ah->qaction ()->setToolTip (tl::to_qstring (tool_tip));
}
if (! res.empty ()) {
ah->qaction ()->setIcon (QIcon (tl::to_qstring (res)));
}
if (! shortcut.empty ()) {
ah->set_default_shortcut (shortcut);
}
}
#if defined(HAVE_QT)
namespace {
/**
* @brief A specialization that provides a way to catch ambiguous key shortcuts
@ -370,6 +352,8 @@ private:
size_t m_id;
};
}
static size_t
id_from_action (QAction *action)
{
@ -377,9 +361,13 @@ id_from_action (QAction *action)
return ao ? ao->id () : 0;
}
Action::Action ()
: mp_menu (0),
#endif
Action::Action () :
#if defined(HAVE_QT)
mp_menu (0),
mp_action (new ActionObject (0)),
#endif
mp_dispatcher (0),
m_owned (true),
m_visible (true),
@ -391,11 +379,14 @@ Action::Action ()
}
sp_actionHandles->insert (this);
#if defined(HAVE_QT)
// catch the destroyed signal to tell if the QAction object is deleted.
connect (mp_action, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *)));
connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ()));
#endif
}
#if defined(HAVE_QT)
Action::Action (QAction *action, bool owned)
: mp_menu (0),
mp_action (action),
@ -433,10 +424,13 @@ Action::Action (QMenu *menu, bool owned)
connect (mp_menu, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *)));
connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ()));
}
#endif
Action::Action (const std::string &title)
: mp_menu (0),
Action::Action (const std::string &title) :
#if defined(HAVE_QT)
mp_menu (0),
mp_action (new QAction (0)),
#endif
mp_dispatcher (0),
m_owned (true),
m_visible (true),
@ -448,11 +442,20 @@ Action::Action (const std::string &title)
}
sp_actionHandles->insert (this);
configure_action_from_title (this, title);
#if !defined(HAVE_QT)
m_checked = false;
m_checkable = false;
m_enabled = true;
m_separator = false;
#endif
configure_from_title (title);
#if defined(HAVE_QT)
// catch the destroyed signal to tell if the QAction object is deleted.
connect (mp_action, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *)));
connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ()));
#endif
}
Action::~Action ()
@ -465,6 +468,7 @@ Action::~Action ()
}
}
#if defined(HAVE_QT)
if (mp_menu) {
if (m_owned) {
delete mp_menu;
@ -479,19 +483,55 @@ Action::~Action ()
}
mp_action = 0;
}
#endif
}
void
Action::set_dispatcher (Dispatcher *dispatcher)
{
if (mp_dispatcher != dispatcher) {
#if defined(HAVE_QT)
if (mp_action && m_owned) {
mp_action->setParent (dispatcher ? dispatcher->menu_parent_widget () : 0);
}
#endif
mp_dispatcher = dispatcher;
}
}
void
Action::configure_from_title (const std::string &s)
{
std::string title;
std::string shortcut;
std::string res;
std::string tool_tip;
parse_menu_title (s, title, shortcut, res, tool_tip);
#if defined(HAVE_QT)
qaction ()->setText (tl::to_qstring (title));
if (! tool_tip.empty ()) {
qaction ()->setToolTip (tl::to_qstring (tool_tip));
}
if (! res.empty ()) {
qaction ()->setIcon (QIcon (tl::to_qstring (res)));
}
if (! shortcut.empty ()) {
set_default_shortcut (shortcut);
}
#else
m_title = title;
m_default_shortcut = shortcut;
m_tooltip = tool_tip;
m_icon = res;
#endif
}
#if defined(HAVE_QT)
void
Action::qaction_triggered ()
{
@ -499,13 +539,18 @@ Action::qaction_triggered ()
triggered ();
END_PROTECTED
}
#endif
void
Action::trigger ()
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->trigger ();
}
#else
triggered ();
#endif
}
void
@ -514,6 +559,7 @@ Action::triggered ()
// .. no action yet, the reimplementation must provide some ..
}
#if defined(HAVE_QT)
QAction *
Action::qaction () const
{
@ -538,16 +584,19 @@ Action::destroyed (QObject *obj)
}
m_owned = false;
}
#endif
void
Action::set_visible (bool v)
{
if (m_visible != v) {
m_visible = v;
#if defined(HAVE_QT)
if (mp_action) {
mp_action->setVisible (is_effective_visible ());
mp_action->setShortcut (get_key_sequence ());
}
#endif
}
}
@ -556,10 +605,12 @@ Action::set_hidden (bool h)
{
if (m_hidden != h) {
m_hidden = h;
#if defined(HAVE_QT)
if (mp_action) {
mp_action->setVisible (is_effective_visible ());
mp_action->setShortcut (get_key_sequence ());
}
#endif
}
}
@ -586,10 +637,12 @@ Action::set_default_shortcut (const std::string &sc)
{
if (m_default_shortcut != sc) {
m_default_shortcut = sc;
#if defined(HAVE_QT)
m_default_key_sequence = QKeySequence (tl::to_qstring (sc));
if (mp_action) {
mp_action->setShortcut (get_key_sequence ());
}
#endif
}
}
@ -599,25 +652,36 @@ Action::set_shortcut (const std::string &sc)
if (m_shortcut != sc) {
m_shortcut = sc;
m_no_key_sequence = (sc == Action::no_shortcut ());
#if defined(HAVE_QT)
m_key_sequence = m_no_key_sequence ? QKeySequence () : QKeySequence (tl::to_qstring (m_shortcut));
if (mp_action) {
mp_action->setShortcut (get_key_sequence ());
}
#endif
}
}
std::string
Action::get_default_shortcut () const
{
#if defined(HAVE_QT)
return tl::to_string (m_default_key_sequence.toString ());
#else
return m_default_shortcut;
#endif
}
std::string
Action::get_shortcut () const
{
#if defined(HAVE_QT)
return m_no_key_sequence ? Action::no_shortcut () : tl::to_string (m_key_sequence.toString ());
#else
return m_no_key_sequence ? Action::no_shortcut () : m_shortcut;
#endif
}
#if defined(HAVE_QT)
QKeySequence
Action::get_key_sequence () const
{
@ -647,6 +711,7 @@ Action::get_key_sequence_for (const std::string &sc) const
return QKeySequence::fromString (tl::to_qstring (sc));
}
}
#endif
const std::string &
Action::no_shortcut ()
@ -658,100 +723,168 @@ Action::no_shortcut ()
void
Action::set_title (const std::string &t)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setText (tl::to_qstring (t));
}
#else
m_title = t;
#endif
}
std::string
Action::get_title () const
{
#if defined(HAVE_QT)
if (qaction ()) {
return tl::to_string (qaction ()->text ());
} else {
return std::string ();
}
#else
return m_title;
#endif
}
std::string
Action::get_effective_shortcut () const
{
#if defined(HAVE_QT)
return tl::to_string (get_key_sequence ().toString ());
#else
if (m_hidden || m_no_key_sequence) {
// A hidden menu item does not have a key sequence too.
return std::string ();
} else if (m_shortcut.empty ()) {
return m_default_shortcut;
} else {
return m_shortcut;
}
#endif
}
std::string
Action::get_effective_shortcut_for (const std::string &sc) const
{
#if defined(HAVE_QT)
return tl::to_string (get_key_sequence_for (sc).toString ());
#else
if (m_hidden) {
// A hidden menu item does not have a key sequence too.
return std::string ();
} else if (sc.empty ()) {
return m_default_shortcut;
} else if (sc == Action::no_shortcut ()) {
return std::string ();
} else {
return sc;
}
#endif
}
void
Action::add_to_exclusive_group (lay::AbstractMenu *menu, const std::string &group_name)
{
// NOTE: this feature does not work without Qt
#if defined(HAVE_QT)
if (qaction ()) {
menu->make_exclusive_group (group_name)->addAction (qaction ());
}
#endif
}
bool
Action::is_checkable () const
{
#if defined(HAVE_QT)
return qaction () && qaction ()->isCheckable ();
#else
return m_checkable;
#endif
}
bool
Action::is_checked () const
{
#if defined(HAVE_QT)
return qaction () && qaction ()->isChecked ();
#else
return m_checked;
#endif
}
bool
Action::is_enabled () const
{
#if defined(HAVE_QT)
return qaction () && qaction ()->isEnabled ();
#else
return m_enabled;
#endif
}
bool
Action::is_separator () const
{
#if defined(HAVE_QT)
return qaction () && qaction ()->isSeparator ();
#else
return m_separator;
#endif
}
void
Action::set_enabled (bool b)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setEnabled (b);
}
#else
m_enabled = b;
#endif
}
void
Action::set_checked (bool c)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setChecked (c);
}
#else
m_checked = c;
#endif
}
void
Action::set_checkable (bool c)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setCheckable (c);
}
#else
m_checkable = c;
#endif
}
void
Action::set_separator (bool s)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setSeparator (s);
}
#else
m_separator = s;
#endif
}
void
Action::set_icon (const std::string &filename)
{
#if defined(HAVE_QT)
if (qaction ()) {
if (filename.empty ()) {
qaction ()->setIcon (QIcon ());
@ -759,21 +892,29 @@ Action::set_icon (const std::string &filename)
qaction ()->setIcon (QIcon (tl::to_qstring (filename)));
}
}
#else
m_icon = filename;
#endif
}
std::string
Action::get_tool_tip () const
{
#if defined(HAVE_QT)
if (qaction ()) {
return tl::to_string (qaction ()->toolTip ());
} else {
return std::string ();
}
#else
return m_tooltip;
#endif
}
void
Action::set_tool_tip (const std::string &text)
{
#if defined(HAVE_QT)
if (qaction ()) {
if (text.empty ()) {
qaction ()->setToolTip (QString ());
@ -781,21 +922,29 @@ Action::set_tool_tip (const std::string &text)
qaction ()->setToolTip (tl::to_qstring (text));
}
}
#else
m_tooltip = text;
#endif
}
std::string
Action::get_icon_text () const
{
#if defined(HAVE_QT)
if (qaction ()) {
return tl::to_string (qaction ()->iconText ());
} else {
return std::string ();
}
#else
return m_icontext;
#endif
}
void
Action::set_icon_text (const std::string &icon_text)
{
#if defined(HAVE_QT)
if (qaction ()) {
if (icon_text.empty ()) {
qaction ()->setIconText (QString ());
@ -803,14 +952,19 @@ Action::set_icon_text (const std::string &icon_text)
qaction ()->setIconText (tl::to_qstring (icon_text));
}
}
#else
m_icontext = icon_text;
#endif
}
void
Action::set_object_name (const std::string &name)
{
#if defined(HAVE_QT)
if (qaction ()) {
qaction ()->setObjectName (tl::to_qstring (name));
}
#endif
}
// ---------------------------------------------------------------
@ -895,6 +1049,7 @@ AbstractMenu::~AbstractMenu ()
// .. nothing yet ..
}
#if defined(HAVE_QT)
QActionGroup *
AbstractMenu::make_exclusive_group (const std::string &name)
{
@ -1195,6 +1350,7 @@ AbstractMenu::menu (const std::string &path)
return 0;
}
}
#endif
bool
AbstractMenu::is_valid (const std::string &path) const
@ -1645,7 +1801,9 @@ void
AbstractMenu::emit_changed ()
{
m_config_actions_valid = false;
#if defined(HAVE_QT)
emit changed ();
#endif
}
std::vector<ConfigureAction *> AbstractMenu::configure_actions (const std::string &name)
@ -1703,5 +1861,3 @@ AbstractMenu::get_shortcuts (const std::string &root, std::map<std::string, std:
}
}
#endif

View File

@ -20,16 +20,16 @@
*/
#if defined(HAVE_QT)
#ifndef HDR_layAbstractMenu
#define HDR_layAbstractMenu
#include <QKeySequence>
#include <QShortcut>
#include <QAction>
#include <QMenu>
#include <QObject>
#if defined(HAVE_QT)
# include <QKeySequence>
# include <QShortcut>
# include <QAction>
# include <QMenu>
# include <QObject>
#endif
#include <string>
#include <set>
@ -43,10 +43,12 @@
#include "tlObject.h"
#include "laybasicCommon.h"
#if defined(HAVE_QT)
class QFrame;
class QMenuBar;
class QToolBar;
class QMenu;
#endif
namespace lay
{
@ -85,12 +87,16 @@ LAYBASIC_PUBLIC std::string pack_menu_items_hidden (const std::vector<std::pair<
*
* This object is typically owned by the AbstractMenu and cannot be copied or assigned.
*/
class LAYBASIC_PUBLIC Action
: public QObject,
class LAYBASIC_PUBLIC Action :
#if defined(HAVE_QT)
public QObject,
#endif
public tl::Object,
public gsi::ObjectBase
{
#if defined(HAVE_QT)
Q_OBJECT
#endif
public:
/**
@ -98,6 +104,7 @@ public:
*/
Action ();
#if defined(HAVE_QT)
/**
* @brief Creates an action from the given QAction
* If "owned" is true, the QAction will become owned by the Action object.
@ -109,6 +116,7 @@ public:
* If "owned" is true, the QAction will become owned by the Action object.
*/
Action (QMenu *menu, bool owned = true);
#endif
/**
* @brief Creates an action with the given title (icon, keyboard shortcut)
@ -310,6 +318,7 @@ public:
return false;
}
#if defined(HAVE_QT)
/**
* @brief Get the underlying QAction object
*
@ -321,6 +330,7 @@ public:
* @brief Gets the QMenu object if the action is a menu action
*/
QMenu *menu () const;
#endif
/**
* @brief Gets the dispatcher object this action is connected to
@ -330,29 +340,48 @@ public:
return mp_dispatcher;
}
#if defined(HAVE_QT)
protected slots:
void destroyed (QObject *obj);
void qaction_triggered ();
#endif
private:
friend struct AbstractMenuItem;
#if defined(HAVE_QT)
QMenu *mp_menu;
QAction *mp_action;
#else
std::string m_title;
std::string m_icon;
std::string m_icontext;
std::string m_tooltip;
bool m_checked;
bool m_checkable;
bool m_enabled;
bool m_separator;
#endif
lay::Dispatcher *mp_dispatcher;
bool m_owned;
bool m_visible;
bool m_hidden;
std::string m_default_shortcut;
QKeySequence m_default_key_sequence;
std::string m_shortcut;
std::string m_symbol;
#if defined(HAVE_QT)
QKeySequence m_default_key_sequence;
QKeySequence m_key_sequence;
#endif
bool m_no_key_sequence;
void set_dispatcher (Dispatcher *dispatcher);
#if defined(HAVE_QT)
QKeySequence get_key_sequence () const;
QKeySequence get_key_sequence_for (const std::string &sc) const;
#endif
void configure_from_title (const std::string &s);
// no copying
Action (const Action &);
@ -501,10 +530,12 @@ struct LAYBASIC_PUBLIC AbstractMenuItem
return mp_action.get ();
}
#if defined(HAVE_QT)
QMenu *menu ()
{
return mp_action->menu ();
}
#endif
void set_has_submenu ();
@ -575,11 +606,15 @@ private:
* QMenu's created so far (except the detached menus), clear the QMenuBar, recreate the QMenu objects (note, that the
* addresses will change this way!) and refill the QToolBar and QMenuBar.
*/
class LAYBASIC_PUBLIC AbstractMenu
: public QObject,
class LAYBASIC_PUBLIC AbstractMenu :
#if defined(HAVE_QT)
public QObject,
#endif
public gsi::ObjectBase
{
#if defined(HAVE_QT)
Q_OBJECT
#endif
public:
/**
@ -592,6 +627,7 @@ public:
*/
~AbstractMenu ();
#if defined(HAVE_QT)
/**
* @brief Rebuild the QMenu's and refill the QMenuBar object
*/
@ -616,6 +652,29 @@ public:
*/
QMenu *menu (const std::string &path);
/**
* @brief Get the detached menu
*
* This will return a QMenu pointer to a detached menu that is created
* with a "@.." top level entry. In any case, a valid QMenu object is returned
* which never changes, even if the menu hierarchy is rebuilt. The QMenu returned
* may be empty.
*
* @param name The name of the detached menu, without the "@"
* @return a valid QMenu object
*/
QMenu *detached_menu (const std::string &name);
/**
* @brief Creates a new exclusive action group
*
* If a group with that name already exists, this method does nothing.
*
* @return The QActionGroup object of that group
*/
QActionGroup *make_exclusive_group (const std::string &name);
#endif
/**
* @brief Get the Action object for a given item
*
@ -752,28 +811,6 @@ public:
*/
std::vector<lay::ConfigureAction *> configure_actions (const std::string &name);
/**
* @brief Get the detached menu
*
* This will return a QMenu pointer to a detached menu that is created
* with a "@.." top level entry. In any case, a valid QMenu object is returned
* which never changes, even if the menu hierarchy is rebuilt. The QMenu returned
* may be empty.
*
* @param name The name of the detached menu, without the "@"
* @return a valid QMenu object
*/
QMenu *detached_menu (const std::string &name);
/**
* @brief Creates a new exclusive action group
*
* If a group with that name already exists, this method does nothing.
*
* @return The QActionGroup object of that group
*/
QActionGroup *make_exclusive_group (const std::string &name);
/**
* @brief Gets the keyboard shortcuts
* @param with_defaults Returns the default shortcuts if true. Otherwise returns the effective shortcut.
@ -794,11 +831,13 @@ public:
return m_root;
}
#if defined(HAVE_QT)
signals:
/**
* @brief this signal is emitted whenever something changes on the menu
*/
void changed ();
#endif
private:
friend class Action;
@ -806,8 +845,10 @@ private:
std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator> > find_item (tl::Extractor &extr);
const AbstractMenuItem *find_item_exact (const std::string &path) const;
AbstractMenuItem *find_item_exact (const std::string &path);
#if defined(HAVE_QT)
void build (QMenu *menu, std::list<AbstractMenuItem> &items);
void build (QToolBar *tbar, std::list<AbstractMenuItem> &items);
#endif
void collect_group (std::vector<std::string> &grp, const std::string &name, const AbstractMenuItem &item) const;
void collect_configure_actions (std::vector<ConfigureAction *> &ca, AbstractMenuItem &item);
void emit_changed ();
@ -815,8 +856,10 @@ private:
Dispatcher *mp_dispatcher;
AbstractMenuItem m_root;
#if defined(HAVE_QT)
tl::stable_vector<QMenu> m_helper_menu_items;
std::map<std::string, QActionGroup *> m_action_groups;
#endif
std::map<std::string, std::vector<ConfigureAction *> > m_config_action_by_name;
bool m_config_actions_valid;
};
@ -824,5 +867,3 @@ private:
}
#endif
#endif // defined(HAVE_QT)

View File

@ -22,6 +22,7 @@
#include "layDispatcher.h"
#include "layAbstractMenu.h"
#include "tlXMLParser.h"
#include "tlXMLWriter.h"
@ -69,25 +70,23 @@ Dispatcher::~Dispatcher ()
void Dispatcher::set_menu_parent_widget (QWidget *menu_parent_widget)
{
mp_menu_parent_widget = menu_parent_widget;
if (mp_menu_parent_widget) {
mp_menu.reset (new lay::AbstractMenu (this));
} else {
mp_menu.reset (0);
}
}
#endif
void Dispatcher::make_menu ()
{
mp_menu.reset (new lay::AbstractMenu (this));
}
bool
Dispatcher::configure (const std::string &name, const std::string &value)
{
#if defined(HAVE_QT)
if (mp_menu) {
std::vector<lay::ConfigureAction *> ca = mp_menu->configure_actions (name);
for (std::vector<lay::ConfigureAction *>::const_iterator a = ca.begin (); a != ca.end (); ++a) {
(*a)->configure (value);
}
}
#endif
if (mp_delegate) {
return mp_delegate->configure (name, value);

View File

@ -222,6 +222,20 @@ public:
*/
bool has_ui () { return menu_parent_widget () != 0; }
#else
/**
* @brief Returns true, if the dispatcher supplies a user interface
*/
bool has_ui () { return false; }
#endif
/**
* @brief Creates the menu object
*
* This method will only have an effect on the root dispatcher.
*/
void make_menu ();
/**
* @brief Gets the AbstractMenu object
*
@ -231,14 +245,6 @@ public:
{
return (dispatcher () == this) ? mp_menu.get () : dispatcher ()->menu ();
}
#else
/**
* @brief Returns true, if the dispatcher supplies a user interface
*/
bool has_ui () { return false; }
#endif
protected:
// capture the configuration events so we can change the value of the configuration actions
@ -249,8 +255,8 @@ private:
Dispatcher (const Dispatcher &);
Dispatcher &operator= (const Dispatcher &);
#if defined(HAVE_QT)
std::unique_ptr<lay::AbstractMenu> mp_menu;
#if defined(HAVE_QT)
QWidget *mp_menu_parent_widget;
#endif
DispatcherDelegate *mp_delegate;

View File

@ -408,6 +408,43 @@ LayoutViewBase::init (db::Manager *mgr)
create_plugins ();
}
void
LayoutViewBase::finish ()
{
// if we're the root dispatcher initialize the menu and build the context menus. No other menus are built so far.
if (dispatcher () == this) {
#if defined(HAVE_QT)
set_menu_parent_widget (widget ());
init_menu ();
menu ()->build (0, 0);
#else
init_menu ();
#endif
}
}
void
LayoutViewBase::init_menu ()
{
make_menu ();
// make the plugins create their menu items
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
// TODO: get rid of the const_cast hack
const_cast <lay::PluginDeclaration *> (&*cls)->init_menu (dispatcher ());
}
// if not in editable mode, hide all entries from "edit_mode" group and show all from the "view_mode" group and vice versa
std::vector<std::string> edit_mode_grp = menu ()->group ("edit_mode");
for (std::vector<std::string>::const_iterator g = edit_mode_grp.begin (); g != edit_mode_grp.end (); ++g) {
menu ()->action (*g)->set_visible (is_editable ());
}
std::vector<std::string> view_mode_grp = menu ()->group ("view_mode");
for (std::vector<std::string>::const_iterator g = view_mode_grp.begin (); g != view_mode_grp.end (); ++g) {
menu ()->action (*g)->set_visible (! is_editable ());
}
}
void
LayoutViewBase::shutdown ()
{

View File

@ -2861,6 +2861,8 @@ protected:
void free_resources ();
void shutdown ();
void finish ();
void init_menu ();
virtual tl::Color default_background_color ();
virtual void do_set_background_color (tl::Color color, tl::Color contrast);

View File

@ -96,8 +96,6 @@ PluginDeclaration::menu_symbols ()
return symbols;
}
#if defined(HAVE_QT)
namespace {
class GenericMenuAction
@ -173,7 +171,9 @@ PluginDeclaration::init_menu (lay::Dispatcher *dispatcher)
}
mp_editable_mode_action.reset (new Action (title));
#if defined(HAVE_QT)
gtf::action_connect (mp_editable_mode_action->qaction (), SIGNAL (triggered ()), this, SLOT (toggle_editable_enabled ()));
#endif
mp_editable_mode_action->set_checkable (true);
mp_editable_mode_action->set_checked (m_editable_enabled);
@ -281,18 +281,14 @@ PluginDeclaration::remove_menu_items (Dispatcher *dispatcher)
m_menu_actions.clear ();
}
#endif
void
PluginDeclaration::set_editable_enabled (bool f)
{
if (f != m_editable_enabled) {
m_editable_enabled = f;
#if defined(HAVE_QT)
if (mp_editable_mode_action.get ()) {
mp_editable_mode_action->set_checked (f);
}
#endif
editable_enabled_changed_event ();
}
}
@ -443,17 +439,6 @@ Plugin::dispatcher ()
return dynamic_cast<Dispatcher *> (p);
}
Dispatcher *
Plugin::dispatcher_maybe_null ()
{
Plugin *p = this;
while (p->mp_parent) {
p = p->mp_parent;
}
return dynamic_cast<Dispatcher *> (p);
}
void
Plugin::do_config_setup (Plugin *target)
{

View File

@ -30,9 +30,7 @@
#include "tlClassRegistry.h"
#include "tlDeferredExecution.h"
#include "gsiObject.h"
#if defined(HAVE_QT)
# include "layAbstractMenu.h"
#endif
#include "layAbstractMenu.h"
#include <map>
#include <vector>
@ -393,7 +391,6 @@ public:
*/
static std::vector<std::string> menu_symbols ();
#if defined(HAVE_QT)
/**
* @brief Creates the menu resources for this plugin
*
@ -407,7 +404,6 @@ public:
* @brief Removes the menu resources associated with this plugin
*/
void remove_menu_items (lay::Dispatcher *dispatcher);
#endif
/**
* @brief Enables this editable part of the plugin
@ -462,11 +458,9 @@ private slots:
private:
int m_id;
#if defined(HAVE_QT)
tl::weak_ptr<lay::Action> mp_editable_mode_action;
tl::weak_ptr<lay::Action> mp_mouse_mode_action;
tl::weak_collection<lay::Action> m_menu_actions;
#endif
bool m_editable_enabled;
};
@ -687,13 +681,6 @@ public:
*/
Dispatcher *dispatcher ();
/**
* @brief Gets the dispatcher (the top level end of the plugin chain)
* This version may return null, if the plugin is instantiated without a
* root.
*/
Dispatcher *dispatcher_maybe_null ();
/**
* @brief Menu command handler
*

View File

@ -16,7 +16,6 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
layPluginConfigPage.cc \
layPropertiesDialog.cc \
layProperties.cc \
layAbstractMenu.cc \
layDragDropData.cc \
layCursor.cc \
@ -25,7 +24,6 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
layPluginConfigPage.h \
layPropertiesDialog.h \
layProperties.h \
layAbstractMenu.h \
layDragDropData.h \
layCursor.h \
@ -35,9 +33,11 @@ SOURCES += \
gsiDeclLayLayers.cc \
gsiDeclLayLayoutViewBase.cc \
gsiDeclLayMarker.cc \
gsiDeclLayMenu.cc \
gsiDeclLayPlugin.cc \
gsiDeclLayTlAdded.cc \
gsiDeclLayRdbAdded.cc \
layAbstractMenu.cc \
layLayoutViewConfig.cc \
laybasicForceLink.cc \
layAnnotationShapes.cc \
@ -90,6 +90,7 @@ SOURCES += \
HEADERS += \
laybasicConfig.h \
laybasicForceLink.h \
layAbstractMenu.h \
layAnnotationShapes.h \
layBitmap.h \
layBitmapRenderer.h \

View File

@ -20,8 +20,6 @@
*/
#if defined(HAVE_QT)
#include "layAbstractMenu.h"
#include "tlUnitTest.h"
@ -185,5 +183,3 @@ TEST(3_ActionReferences)
// the action is deleted because it's owned by the menu
EXPECT_EQ (action.get () == 0, true);
}
#endif

View File

@ -80,7 +80,6 @@ RESOURCES = \
SOURCES = \
gsiDeclLayDialogs.cc \
gsiDeclLayMenu.cc \
gsiDeclLayNetlistBrowserDialog.cc \
gsiDeclLayStream.cc \
layuiForceLink.cc \

View File

@ -31,12 +31,14 @@ LayoutView::LayoutView (db::Manager *mgr, bool editable, lay::Plugin *plugin_par
: LayoutViewBase (this, mgr, editable, plugin_parent, options)
{
config_setup ();
finish ();
}
LayoutView::LayoutView (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, unsigned int options)
: LayoutViewBase (this, source, mgr, editable, plugin_parent, options)
{
config_setup ();
finish ();
}
// NOTE: this methods needs to be called "frequently"

View File

@ -241,26 +241,6 @@ LayoutView::event_filter (QObject *obj, QEvent *event, bool &taken)
return false;
}
void
LayoutView::init_menu ()
{
// make the plugins create their menu items
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
// TODO: get rid of the const_cast hack
const_cast <lay::PluginDeclaration *> (&*cls)->init_menu (dispatcher ());
}
// if not in editable mode, hide all entries from "edit_mode" group and show all from the "view_mode" group and vice versa
std::vector<std::string> edit_mode_grp = menu ()->group ("edit_mode");
for (std::vector<std::string>::const_iterator g = edit_mode_grp.begin (); g != edit_mode_grp.end (); ++g) {
menu ()->action (*g)->set_visible (is_editable ());
}
std::vector<std::string> view_mode_grp = menu ()->group ("view_mode");
for (std::vector<std::string>::const_iterator g = view_mode_grp.begin (); g != view_mode_grp.end (); ++g) {
menu ()->action (*g)->set_visible (! is_editable ());
}
}
void
LayoutView::init_ui (QWidget *parent, const char *name)
{
@ -406,6 +386,7 @@ LayoutView::init_ui (QWidget *parent, const char *name)
}
config_setup ();
finish ();
}
LayoutView::~LayoutView ()

View File

@ -741,7 +741,6 @@ private:
QSize size_hint () const;
void init_ui (QWidget *parent, const char *name);
void init_menu ();
void do_setup_editor_options_pages ();
protected: