mirror of https://github.com/KLayout/klayout.git
Some changes to work around MacOS menu issues
- ID's are used instead of pointers to identify menu items vs. QAction's. This is a weak measure to enhance predictability. - The file menu is built from abstract menu items instead with native Qt objects. This way the bug fix applies both to file menu items and the other menu entries The main fix is: - A menu sync is forced by emitting a focusWindowChanged event from the application object. This forces the QCocoaMenuBar implementation to update the system menu.
This commit is contained in:
parent
fb69dfd866
commit
396d0263d4
|
|
@ -1380,6 +1380,17 @@ GuiApplication::notify (QObject *receiver, QEvent *e)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GuiApplication::force_update_app_menu ()
|
||||||
|
{
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
// This is a workaround for a bug in the MacOS native menu integration:
|
||||||
|
// this signal forces the menu to become updated. Without this, any
|
||||||
|
// new menu items stay disabled.
|
||||||
|
emit focusWindowChanged (focusWindow ());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
GuiApplication::exec ()
|
GuiApplication::exec ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,12 @@ public:
|
||||||
return mp_mw;
|
return mp_mw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Forces update of the application menu
|
||||||
|
* This function is used for work around a MacOS issue.
|
||||||
|
*/
|
||||||
|
void force_update_app_menu ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void setup ();
|
virtual void setup ();
|
||||||
virtual void shutdown ();
|
virtual void shutdown ();
|
||||||
|
|
|
||||||
|
|
@ -450,6 +450,7 @@ MainWindow::MainWindow (QApplication *app, const char *name)
|
||||||
m_disable_tab_selected (false),
|
m_disable_tab_selected (false),
|
||||||
m_exited (false),
|
m_exited (false),
|
||||||
dm_do_update_menu (this, &MainWindow::do_update_menu),
|
dm_do_update_menu (this, &MainWindow::do_update_menu),
|
||||||
|
dm_do_update_file_menu (this, &MainWindow::do_update_file_menu),
|
||||||
dm_exit (this, &MainWindow::exit),
|
dm_exit (this, &MainWindow::exit),
|
||||||
m_grid_micron (0.001),
|
m_grid_micron (0.001),
|
||||||
m_default_grids_updated (true),
|
m_default_grids_updated (true),
|
||||||
|
|
@ -613,10 +614,6 @@ MainWindow::MainWindow (QApplication *app, const char *name)
|
||||||
tl_assert (bookmark_menu != 0);
|
tl_assert (bookmark_menu != 0);
|
||||||
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
|
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
|
||||||
|
|
||||||
QMenu *file_menu = mp_menu->menu ("file_menu");
|
|
||||||
tl_assert (file_menu != 0);
|
|
||||||
connect (file_menu, SIGNAL (aboutToShow ()), this, SLOT (file_menu_show ()));
|
|
||||||
|
|
||||||
// select the default mode
|
// select the default mode
|
||||||
select_mode (lay::LayoutView::default_mode ());
|
select_mode (lay::LayoutView::default_mode ());
|
||||||
|
|
||||||
|
|
@ -1595,6 +1592,8 @@ MainWindow::configure (const std::string &name, const std::string &value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dm_do_update_file_menu ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else if (name == cfg_micron_digits) {
|
} else if (name == cfg_micron_digits) {
|
||||||
|
|
@ -4173,30 +4172,31 @@ MainWindow::add_mru (const std::string &fn_rel, const std::string &tech)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWindow::file_menu_show ()
|
MainWindow::do_update_file_menu ()
|
||||||
{
|
{
|
||||||
if (mp_menu->is_valid ("file_menu.open_recent_menu")) {
|
std::string mru_menu = "file_menu.open_recent_menu";
|
||||||
|
|
||||||
Action open_recent_action = mp_menu->action ("file_menu.open_recent_menu");
|
if (mp_menu->is_valid (mru_menu)) {
|
||||||
|
|
||||||
|
Action open_recent_action = mp_menu->action (mru_menu);
|
||||||
|
open_recent_action.set_enabled (true);
|
||||||
|
|
||||||
if (m_mru.size () > 0 && edits_enabled ()) {
|
if (m_mru.size () > 0 && edits_enabled ()) {
|
||||||
|
|
||||||
open_recent_action.set_enabled (true);
|
// rebuild MRU menu
|
||||||
|
std::vector<std::string> items = mp_menu->items (mru_menu);
|
||||||
QMenu *open_recent_menu = open_recent_action.qaction ()->menu ();
|
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
||||||
if (open_recent_menu) {
|
mp_menu->delete_item (mru_menu + "." + *i);
|
||||||
|
}
|
||||||
open_recent_menu->clear ();
|
|
||||||
|
|
||||||
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
|
|
||||||
--mru;
|
|
||||||
unsigned int i = std::distance (m_mru.begin (), mru);
|
|
||||||
QAction *action = open_recent_menu->addAction (tl::to_qstring (mru->first));
|
|
||||||
action->setObjectName (tl::to_qstring (tl::sprintf ("open_recent_%d", i + 1)));
|
|
||||||
gtf::action_connect (action, SIGNAL (triggered ()), this, SLOT (open_recent ()));
|
|
||||||
action->setData (QVariant (int (i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
|
||||||
|
--mru;
|
||||||
|
unsigned int i = std::distance (m_mru.begin (), mru);
|
||||||
|
Action action;
|
||||||
|
gtf::action_connect (action.qaction (), SIGNAL (triggered ()), this, SLOT (open_recent ()));
|
||||||
|
action.set_title (mru->first);
|
||||||
|
action.qaction ()->setData (QVariant (int (i)));
|
||||||
|
mp_menu->insert_item (mru_menu + ".end", tl::sprintf ("open_recent_%d", i + 1), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -5016,6 +5016,10 @@ void
|
||||||
MainWindow::do_update_menu ()
|
MainWindow::do_update_menu ()
|
||||||
{
|
{
|
||||||
mp_menu->build (menuBar (), mp_tool_bar);
|
mp_menu->build (menuBar (), mp_tool_bar);
|
||||||
|
lay::GuiApplication *app = dynamic_cast<lay::GuiApplication *> (qApp);
|
||||||
|
if (app) {
|
||||||
|
app->force_update_app_menu ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -859,7 +859,6 @@ protected slots:
|
||||||
void menu_changed ();
|
void menu_changed ();
|
||||||
void message_timer ();
|
void message_timer ();
|
||||||
void bookmark_menu_show ();
|
void bookmark_menu_show ();
|
||||||
void file_menu_show ();
|
|
||||||
void edits_enabled_changed ();
|
void edits_enabled_changed ();
|
||||||
void file_changed_timer ();
|
void file_changed_timer ();
|
||||||
void file_changed (const QString &path);
|
void file_changed (const QString &path);
|
||||||
|
|
@ -868,6 +867,7 @@ protected slots:
|
||||||
protected:
|
protected:
|
||||||
void update_content ();
|
void update_content ();
|
||||||
void do_update_menu ();
|
void do_update_menu ();
|
||||||
|
void do_update_file_menu ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextProgressDelegate m_text_progress;
|
TextProgressDelegate m_text_progress;
|
||||||
|
|
@ -911,6 +911,7 @@ private:
|
||||||
bool m_disable_tab_selected;
|
bool m_disable_tab_selected;
|
||||||
bool m_exited;
|
bool m_exited;
|
||||||
tl::DeferredMethod<MainWindow> dm_do_update_menu;
|
tl::DeferredMethod<MainWindow> dm_do_update_menu;
|
||||||
|
tl::DeferredMethod<MainWindow> dm_do_update_file_menu;
|
||||||
tl::DeferredMethod<MainWindow> dm_exit;
|
tl::DeferredMethod<MainWindow> dm_exit;
|
||||||
QTimer m_message_timer;
|
QTimer m_message_timer;
|
||||||
QTimer m_file_changed_timer;
|
QTimer m_file_changed_timer;
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ static const bool s_can_move_menu = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Helper function to parse a title with potential shortcut and
|
// Helper function to parse a title with potential shortcut and
|
||||||
// icon specification
|
// icon specification
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -122,19 +122,19 @@ parse_menu_title (const std::string &s, std::string &title, std::string &shortcu
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// AbstractMenuItem implementation
|
// AbstractMenuItem implementation
|
||||||
|
|
||||||
AbstractMenuItem::AbstractMenuItem ()
|
AbstractMenuItem::AbstractMenuItem ()
|
||||||
: m_has_submenu (false), m_remove_on_empty (false)
|
: m_has_submenu (false), m_remove_on_empty (false)
|
||||||
{
|
{
|
||||||
// ... nothing yet ..
|
// ... nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &)
|
AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &)
|
||||||
: m_has_submenu (false), m_remove_on_empty (false)
|
: m_has_submenu (false), m_remove_on_empty (false)
|
||||||
{
|
{
|
||||||
// ... nothing yet ..
|
// ... nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const Action &a)
|
AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const Action &a)
|
||||||
{
|
{
|
||||||
m_basename.clear ();
|
m_basename.clear ();
|
||||||
|
|
@ -162,7 +162,7 @@ AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const
|
||||||
set_action (a, false);
|
set_action (a, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenuItem::set_action (const Action &a, bool copy_properties)
|
AbstractMenuItem::set_action (const Action &a, bool copy_properties)
|
||||||
{
|
{
|
||||||
Action acopy = a;
|
Action acopy = a;
|
||||||
|
|
@ -187,13 +187,13 @@ AbstractMenuItem::set_action (const Action &a, bool copy_properties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenuItem::set_action_title (const std::string &s)
|
AbstractMenuItem::set_action_title (const std::string &s)
|
||||||
{
|
{
|
||||||
m_action.set_title (s);
|
m_action.set_title (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenuItem::set_has_submenu ()
|
AbstractMenuItem::set_has_submenu ()
|
||||||
{
|
{
|
||||||
m_has_submenu = true;
|
m_has_submenu = true;
|
||||||
|
|
@ -214,10 +214,20 @@ static std::set<ActionHandle *> *sp_actionHandles = 0;
|
||||||
* @brief A specialization that provides a way to catch ambiguous key shortcuts
|
* @brief A specialization that provides a way to catch ambiguous key shortcuts
|
||||||
*/
|
*/
|
||||||
class ActionObject
|
class ActionObject
|
||||||
: public QAction
|
: public QAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ActionObject (QObject *parent) : QAction (parent) { }
|
ActionObject (QObject *parent)
|
||||||
|
: QAction (parent)
|
||||||
|
{
|
||||||
|
static size_t s_id = 0;
|
||||||
|
m_id = ++s_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t id () const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
bool event(QEvent *e)
|
bool event(QEvent *e)
|
||||||
{
|
{
|
||||||
|
|
@ -251,8 +261,18 @@ public:
|
||||||
|
|
||||||
return QAction::event(e);
|
return QAction::event(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
id_from_action (QAction *action)
|
||||||
|
{
|
||||||
|
ActionObject *ao = dynamic_cast<ActionObject *> (action);
|
||||||
|
return ao ? ao->id () : 0;
|
||||||
|
}
|
||||||
|
|
||||||
ActionHandle::ActionHandle (QWidget *parent)
|
ActionHandle::ActionHandle (QWidget *parent)
|
||||||
: mp_menu (0),
|
: mp_menu (0),
|
||||||
mp_action (new ActionObject (parent)),
|
mp_action (new ActionObject (parent)),
|
||||||
|
|
@ -260,7 +280,7 @@ ActionHandle::ActionHandle (QWidget *parent)
|
||||||
m_owned (true),
|
m_owned (true),
|
||||||
m_visible (true),
|
m_visible (true),
|
||||||
m_hidden (false)
|
m_hidden (false)
|
||||||
{
|
{
|
||||||
if (! sp_actionHandles) {
|
if (! sp_actionHandles) {
|
||||||
sp_actionHandles = new std::set<ActionHandle *> ();
|
sp_actionHandles = new std::set<ActionHandle *> ();
|
||||||
}
|
}
|
||||||
|
|
@ -273,11 +293,11 @@ ActionHandle::ActionHandle (QWidget *parent)
|
||||||
ActionHandle::ActionHandle (QAction *action, bool owned)
|
ActionHandle::ActionHandle (QAction *action, bool owned)
|
||||||
: mp_menu (0),
|
: mp_menu (0),
|
||||||
mp_action (action),
|
mp_action (action),
|
||||||
m_ref_count (0),
|
m_ref_count (0),
|
||||||
m_owned (owned),
|
m_owned (owned),
|
||||||
m_visible (true),
|
m_visible (true),
|
||||||
m_hidden (false)
|
m_hidden (false)
|
||||||
{
|
{
|
||||||
if (! sp_actionHandles) {
|
if (! sp_actionHandles) {
|
||||||
sp_actionHandles = new std::set<ActionHandle *> ();
|
sp_actionHandles = new std::set<ActionHandle *> ();
|
||||||
}
|
}
|
||||||
|
|
@ -330,13 +350,13 @@ ActionHandle::~ActionHandle ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ActionHandle::add_ref ()
|
ActionHandle::add_ref ()
|
||||||
{
|
{
|
||||||
++m_ref_count;
|
++m_ref_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ActionHandle::remove_ref ()
|
ActionHandle::remove_ref ()
|
||||||
{
|
{
|
||||||
if (--m_ref_count == 0) {
|
if (--m_ref_count == 0) {
|
||||||
|
|
@ -356,7 +376,7 @@ ActionHandle::menu () const
|
||||||
return mp_menu;
|
return mp_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ActionHandle::destroyed (QObject * /*obj*/)
|
ActionHandle::destroyed (QObject * /*obj*/)
|
||||||
{
|
{
|
||||||
mp_action = 0;
|
mp_action = 0;
|
||||||
|
|
@ -548,7 +568,7 @@ Action::triggered_slot ()
|
||||||
END_PROTECTED
|
END_PROTECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_title (const std::string &t)
|
Action::set_title (const std::string &t)
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -556,7 +576,7 @@ Action::set_title (const std::string &t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Action::get_title () const
|
Action::get_title () const
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -566,7 +586,7 @@ Action::get_title () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_shortcut (const QKeySequence &s)
|
Action::set_shortcut (const QKeySequence &s)
|
||||||
{
|
{
|
||||||
if (mp_handle) {
|
if (mp_handle) {
|
||||||
|
|
@ -732,7 +752,7 @@ Action::set_separator (bool s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_icon (const std::string &filename)
|
Action::set_icon (const std::string &filename)
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -744,7 +764,7 @@ Action::set_icon (const std::string &filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Action::get_tool_tip () const
|
Action::get_tool_tip () const
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -754,7 +774,7 @@ Action::get_tool_tip () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_tool_tip (const std::string &text)
|
Action::set_tool_tip (const std::string &text)
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -766,7 +786,7 @@ Action::set_tool_tip (const std::string &text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Action::get_icon_text () const
|
Action::get_icon_text () const
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -776,7 +796,7 @@ Action::get_icon_text () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_icon_text (const std::string &icon_text)
|
Action::set_icon_text (const std::string &icon_text)
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -788,7 +808,7 @@ Action::set_icon_text (const std::string &icon_text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Action::set_object_name (const std::string &name)
|
Action::set_object_name (const std::string &name)
|
||||||
{
|
{
|
||||||
if (qaction ()) {
|
if (qaction ()) {
|
||||||
|
|
@ -814,7 +834,7 @@ ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &cname,
|
||||||
}
|
}
|
||||||
|
|
||||||
reg ();
|
reg ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title, const std::string &cname, const std::string &cvalue)
|
ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title, const std::string &cname, const std::string &cvalue)
|
||||||
: Action (title), m_pr (pr), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type)
|
: Action (title), m_pr (pr), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type)
|
||||||
|
|
@ -831,19 +851,19 @@ ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title,
|
||||||
}
|
}
|
||||||
|
|
||||||
reg ();
|
reg ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureAction::~ConfigureAction ()
|
ConfigureAction::~ConfigureAction ()
|
||||||
{
|
{
|
||||||
unreg ();
|
unreg ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConfigureAction::triggered ()
|
ConfigureAction::triggered ()
|
||||||
{
|
{
|
||||||
if (m_type == boolean_type) {
|
if (m_type == boolean_type) {
|
||||||
m_cvalue = tl::to_string (is_checked ());
|
m_cvalue = tl::to_string (is_checked ());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pr->config_set (m_cname, m_cvalue);
|
m_pr->config_set (m_cname, m_cvalue);
|
||||||
}
|
}
|
||||||
|
|
@ -880,7 +900,7 @@ ConfigureAction::configure (const std::string &value)
|
||||||
set_checkable (true);
|
set_checkable (true);
|
||||||
set_checked (m_cvalue == value);
|
set_checked (m_cvalue == value);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
@ -897,7 +917,7 @@ AbstractMenu::create_action (const std::string &s)
|
||||||
std::string tool_tip;
|
std::string tool_tip;
|
||||||
|
|
||||||
parse_menu_title (s, title, shortcut, res, tool_tip);
|
parse_menu_title (s, title, shortcut, res, tool_tip);
|
||||||
|
|
||||||
ActionHandle *ah = new ActionHandle (lay::AbstractMenuProvider::instance ()->menu_parent_widget ());
|
ActionHandle *ah = new ActionHandle (lay::AbstractMenuProvider::instance ()->menu_parent_widget ());
|
||||||
ah->ptr ()->setText (tl::to_qstring (title));
|
ah->ptr ()->setText (tl::to_qstring (title));
|
||||||
|
|
||||||
|
|
@ -927,7 +947,7 @@ AbstractMenu::~AbstractMenu ()
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::init (const MenuLayoutEntry *layout)
|
AbstractMenu::init (const MenuLayoutEntry *layout)
|
||||||
{
|
{
|
||||||
m_root.set_has_submenu ();
|
m_root.set_has_submenu ();
|
||||||
|
|
@ -943,12 +963,12 @@ AbstractMenu::make_exclusive_group (const std::string &name)
|
||||||
QActionGroup *ag = new QActionGroup (this);
|
QActionGroup *ag = new QActionGroup (this);
|
||||||
ag->setExclusive (true);
|
ag->setExclusive (true);
|
||||||
a = m_action_groups.insert (std::make_pair (name, ag)).first;
|
a = m_action_groups.insert (std::make_pair (name, ag)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return a->second;
|
return a->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
|
AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
|
||||||
{
|
{
|
||||||
// Clean up the menu bar before rebuilding
|
// Clean up the menu bar before rebuilding
|
||||||
|
|
@ -1005,7 +1025,7 @@ AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
|
||||||
menu_layout->addStretch (1);
|
menu_layout->addStretch (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
{
|
{
|
||||||
tl_assert (mp_provider != 0);
|
tl_assert (mp_provider != 0);
|
||||||
|
|
@ -1013,9 +1033,11 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
m_helper_menu_items.clear ();
|
m_helper_menu_items.clear ();
|
||||||
tbar->clear ();
|
tbar->clear ();
|
||||||
|
|
||||||
std::set<QAction *> present_actions;
|
std::set<std::pair<size_t, QAction *> > present_actions;
|
||||||
QList<QAction *> a = mbar->actions ();
|
QList<QAction *> a = mbar->actions ();
|
||||||
present_actions.insert (a.begin (), a.end ());
|
for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) {
|
||||||
|
present_actions.insert (std::make_pair (id_from_action (*i), *i));
|
||||||
|
}
|
||||||
|
|
||||||
for (std::list<AbstractMenuItem>::iterator c = m_root.children.begin (); c != m_root.children.end (); ++c) {
|
for (std::list<AbstractMenuItem>::iterator c = m_root.children.begin (); c != m_root.children.end (); ++c) {
|
||||||
|
|
||||||
|
|
@ -1027,7 +1049,7 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
|
|
||||||
} else if (c->name ().find ("@@") == 0) {
|
} else if (c->name ().find ("@@") == 0) {
|
||||||
|
|
||||||
// nothing: let build_detached build the menu
|
// nothing: let build_detached build the menu
|
||||||
|
|
||||||
} else if (c->name ().find ("@") == 0) {
|
} else if (c->name ().find ("@") == 0) {
|
||||||
|
|
||||||
|
|
@ -1035,9 +1057,9 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
QMenu *menu = new QMenu (tl::to_qstring (c->action ().get_title ()));
|
QMenu *menu = new QMenu (tl::to_qstring (c->action ().get_title ()));
|
||||||
// HINT: it is necessary to add the menu action to a widget below the main window.
|
// HINT: it is necessary to add the menu action to a widget below the main window.
|
||||||
// Otherwise, the keyboard shortcuts do not work for menu items inside such a
|
// Otherwise, the keyboard shortcuts do not work for menu items inside such a
|
||||||
// popup menu. It seems not to have a negative effect to add the menu to the
|
// popup menu. It seems not to have a negative effect to add the menu to the
|
||||||
// main widget.
|
// main widget.
|
||||||
mp_provider->menu_parent_widget ()->addAction (menu->menuAction ());
|
mp_provider->menu_parent_widget ()->addAction (menu->menuAction ());
|
||||||
c->set_action (Action (new ActionHandle (menu)), true);
|
c->set_action (Action (new ActionHandle (menu)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1053,10 +1075,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
c->set_action (Action (new ActionHandle (menu)), true);
|
c->set_action (Action (new ActionHandle (menu)), true);
|
||||||
} else {
|
} else {
|
||||||
// Move the action to the end if present in the menu already
|
// Move the action to the end if present in the menu already
|
||||||
std::set<QAction *>::iterator a = present_actions.find (c->menu ()->menuAction ());
|
std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->menu ()->menuAction ()), c->menu ()->menuAction ()));
|
||||||
if (a != present_actions.end ()) {
|
if (a != present_actions.end ()) {
|
||||||
if (s_can_move_menu) {
|
if (s_can_move_menu) {
|
||||||
mbar->removeAction (*a);
|
mbar->removeAction (a->second);
|
||||||
mbar->addMenu (c->menu ());
|
mbar->addMenu (c->menu ());
|
||||||
}
|
}
|
||||||
present_actions.erase (*a);
|
present_actions.erase (*a);
|
||||||
|
|
@ -1071,10 +1093,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Move the action to the end if present in the menu already
|
// Move the action to the end if present in the menu already
|
||||||
std::set<QAction *>::iterator a = present_actions.find (c->action ().qaction ());
|
std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->action ().qaction ()), c->action ().qaction ()));
|
||||||
if (a != present_actions.end ()) {
|
if (a != present_actions.end ()) {
|
||||||
if (s_can_move_menu) {
|
if (s_can_move_menu) {
|
||||||
mbar->removeAction (*a);
|
mbar->removeAction (a->second);
|
||||||
mbar->addAction (c->action ().qaction ());
|
mbar->addAction (c->action ().qaction ());
|
||||||
}
|
}
|
||||||
present_actions.erase (*a);
|
present_actions.erase (*a);
|
||||||
|
|
@ -1086,17 +1108,19 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all actions that have vanished
|
// Remove all actions that have vanished
|
||||||
for (std::set<QAction *>::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
|
for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
|
||||||
mbar->removeAction (*a);
|
mbar->removeAction (a->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
|
AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
|
||||||
{
|
{
|
||||||
std::set<QAction *> present_actions;
|
std::set<std::pair<size_t, QAction *> > present_actions;
|
||||||
QList<QAction *> a = m->actions ();
|
QList<QAction *> a = m->actions ();
|
||||||
present_actions.insert (a.begin (), a.end ());
|
for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) {
|
||||||
|
present_actions.insert (std::make_pair (id_from_action (*i), *i));
|
||||||
|
}
|
||||||
|
|
||||||
for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
|
for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
|
||||||
|
|
||||||
|
|
@ -1111,10 +1135,10 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
|
||||||
c->set_action (Action (new ActionHandle (menu)), true);
|
c->set_action (Action (new ActionHandle (menu)), true);
|
||||||
} else {
|
} else {
|
||||||
// Move the action to the end if present in the menu already
|
// Move the action to the end if present in the menu already
|
||||||
std::set<QAction *>::iterator a = present_actions.find (c->menu ()->menuAction ());
|
std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->menu ()->menuAction ()), c->menu ()->menuAction ()));
|
||||||
if (a != present_actions.end ()) {
|
if (a != present_actions.end ()) {
|
||||||
if (s_can_move_menu) {
|
if (s_can_move_menu) {
|
||||||
m->removeAction (*a);
|
m->removeAction (a->second);
|
||||||
m->addMenu (c->menu ());
|
m->addMenu (c->menu ());
|
||||||
}
|
}
|
||||||
present_actions.erase (*a);
|
present_actions.erase (*a);
|
||||||
|
|
@ -1128,10 +1152,10 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Move the action to the end if present in the menu already
|
// Move the action to the end if present in the menu already
|
||||||
std::set<QAction *>::iterator a = present_actions.find (c->action ().qaction ());
|
std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->action ().qaction ()), c->action ().qaction ()));
|
||||||
if (a != present_actions.end ()) {
|
if (a != present_actions.end ()) {
|
||||||
if (s_can_move_menu) {
|
if (s_can_move_menu) {
|
||||||
m->removeAction (*a);
|
m->removeAction (a->second);
|
||||||
m->addAction (c->action ().qaction ());
|
m->addAction (c->action ().qaction ());
|
||||||
}
|
}
|
||||||
present_actions.erase (*a);
|
present_actions.erase (*a);
|
||||||
|
|
@ -1143,26 +1167,26 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all actions that have vanished
|
// Remove all actions that have vanished
|
||||||
for (std::set<QAction *>::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
|
for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
|
||||||
m->removeAction (*a);
|
m->removeAction (a->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::build (QToolBar *t, std::list<AbstractMenuItem> &items)
|
AbstractMenu::build (QToolBar *t, std::list<AbstractMenuItem> &items)
|
||||||
{
|
{
|
||||||
for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
|
for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
|
||||||
|
|
||||||
if (! c->children.empty ()) {
|
if (! c->children.empty ()) {
|
||||||
|
|
||||||
// To support tool buttons with menu we have to attach a helper menu
|
// To support tool buttons with menu we have to attach a helper menu
|
||||||
// item to the QAction object.
|
// item to the QAction object.
|
||||||
// TODO: this hurts if we use this QAction otherwise. In this case, this
|
// TODO: this hurts if we use this QAction otherwise. In this case, this
|
||||||
// QAction would get a menu too. However, hopefully this usage is constrained
|
// QAction would get a menu too. However, hopefully this usage is constrained
|
||||||
// to special toolbar buttons only.
|
// to special toolbar buttons only.
|
||||||
// In order to be able to manage the QMenu ourselves, we must not give it a parent.
|
// In order to be able to manage the QMenu ourselves, we must not give it a parent.
|
||||||
QMenu *menu = new QMenu (0);
|
QMenu *menu = new QMenu (0);
|
||||||
m_helper_menu_items.push_back (menu); // will be owned by the stable vector
|
m_helper_menu_items.push_back (menu); // will be owned by the stable vector
|
||||||
c->action ().qaction ()->setMenu (menu);
|
c->action ().qaction ()->setMenu (menu);
|
||||||
t->addAction (c->action ().qaction ());
|
t->addAction (c->action ().qaction ());
|
||||||
build (menu, c->children);
|
build (menu, c->children);
|
||||||
|
|
@ -1183,7 +1207,7 @@ AbstractMenu::detached_menu (const std::string &name)
|
||||||
}
|
}
|
||||||
|
|
||||||
QMenu *
|
QMenu *
|
||||||
AbstractMenu::menu (const std::string &path)
|
AbstractMenu::menu (const std::string &path)
|
||||||
{
|
{
|
||||||
AbstractMenuItem *item = find_item_exact (path);
|
AbstractMenuItem *item = find_item_exact (path);
|
||||||
if (item) {
|
if (item) {
|
||||||
|
|
@ -1214,7 +1238,7 @@ AbstractMenu::is_separator (const std::string &path) const
|
||||||
return item != 0 && item->action ().is_separator ();
|
return item != 0 && item->action ().is_separator ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
AbstractMenu::action (const std::string &path) const
|
AbstractMenu::action (const std::string &path) const
|
||||||
{
|
{
|
||||||
const AbstractMenuItem *item = find_item_exact (path);
|
const AbstractMenuItem *item = find_item_exact (path);
|
||||||
|
|
@ -1224,7 +1248,7 @@ AbstractMenu::action (const std::string &path) const
|
||||||
return item->action ();
|
return item->action ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
AbstractMenu::items (const std::string &path) const
|
AbstractMenu::items (const std::string &path) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> res;
|
std::vector<std::string> res;
|
||||||
|
|
@ -1240,7 +1264,7 @@ AbstractMenu::items (const std::string &path) const
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::insert_item (const std::string &p, const std::string &name, const Action &action)
|
AbstractMenu::insert_item (const std::string &p, const std::string &name, const Action &action)
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
||||||
|
|
@ -1271,7 +1295,7 @@ AbstractMenu::insert_item (const std::string &p, const std::string &name, const
|
||||||
emit changed ();
|
emit changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::insert_separator (const std::string &p, const std::string &name)
|
AbstractMenu::insert_separator (const std::string &p, const std::string &name)
|
||||||
{
|
{
|
||||||
tl_assert (mp_provider != 0); // required to get the parent for the new QAction (via ActionHandle)
|
tl_assert (mp_provider != 0); // required to get the parent for the new QAction (via ActionHandle)
|
||||||
|
|
@ -1294,7 +1318,7 @@ AbstractMenu::insert_separator (const std::string &p, const std::string &name)
|
||||||
emit changed ();
|
emit changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::insert_menu (const std::string &p, const std::string &name, const Action &action)
|
AbstractMenu::insert_menu (const std::string &p, const std::string &name, const Action &action)
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
||||||
|
|
@ -1324,13 +1348,13 @@ AbstractMenu::insert_menu (const std::string &p, const std::string &name, const
|
||||||
emit changed ();
|
emit changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::insert_menu (const std::string &path, const std::string &name, const std::string &title)
|
AbstractMenu::insert_menu (const std::string &path, const std::string &name, const std::string &title)
|
||||||
{
|
{
|
||||||
insert_menu (path, name, create_action (title));
|
insert_menu (path, name, create_action (title));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::delete_item (const std::string &p)
|
AbstractMenu::delete_item (const std::string &p)
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
|
||||||
|
|
@ -1387,7 +1411,7 @@ AbstractMenu::find_item_exact (const std::string &path) const
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractMenuItem *
|
AbstractMenuItem *
|
||||||
AbstractMenu::find_item_exact (const std::string &path)
|
AbstractMenu::find_item_exact (const std::string &path)
|
||||||
{
|
{
|
||||||
tl::Extractor extr (path.c_str ());
|
tl::Extractor extr (path.c_str ());
|
||||||
AbstractMenuItem *item = &m_root;
|
AbstractMenuItem *item = &m_root;
|
||||||
|
|
@ -1406,7 +1430,7 @@ AbstractMenu::find_item_exact (const std::string &path)
|
||||||
}
|
}
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
item = &*c;
|
item = &*c;
|
||||||
|
|
||||||
|
|
@ -1576,7 +1600,7 @@ AbstractMenu::find_item (const std::string &p)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
|
AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
|
||||||
{
|
{
|
||||||
tl_assert (mp_provider != 0);
|
tl_assert (mp_provider != 0);
|
||||||
|
|
@ -1609,7 +1633,7 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
|
||||||
std::string tool_tip;
|
std::string tool_tip;
|
||||||
|
|
||||||
parse_menu_title (layout->title, title, shortcut, res, tool_tip);
|
parse_menu_title (layout->title, title, shortcut, res, tool_tip);
|
||||||
|
|
||||||
a.set_separator (false);
|
a.set_separator (false);
|
||||||
a.set_title (title);
|
a.set_title (title);
|
||||||
|
|
||||||
|
|
@ -1641,7 +1665,7 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
AbstractMenu::group (const std::string &name) const
|
AbstractMenu::group (const std::string &name) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> grp;
|
std::vector<std::string> grp;
|
||||||
|
|
@ -1649,7 +1673,7 @@ AbstractMenu::group (const std::string &name) const
|
||||||
return grp;
|
return grp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AbstractMenu::collect_group (std::vector<std::string> &grp, const std::string &name, const AbstractMenuItem &item) const
|
AbstractMenu::collect_group (std::vector<std::string> &grp, const std::string &name, const AbstractMenuItem &item) const
|
||||||
{
|
{
|
||||||
for (std::list<AbstractMenuItem>::const_iterator c = item.children.begin (); c != item.children.end (); ++c) {
|
for (std::list<AbstractMenuItem>::const_iterator c = item.children.begin (); c != item.children.end (); ++c) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue