Reworked bookmark menu implementation to avoid MacOS menu issue

Without this commit, bookmark menus got grayed out
on MacOS with Qt5 sometimes. Now, the implementation
of recent file menu, bookmark menu, macro menu and
the static main menu use the same framewkork which
includes a workaround for the disabled menu issue.
This commit is contained in:
Matthias Koefferlein 2018-02-10 18:40:24 +01:00
parent 1e29b29c13
commit 6a762db29b
7 changed files with 127 additions and 77 deletions

View File

@ -609,11 +609,6 @@ MainWindow::MainWindow (QApplication *app, const char *name)
cp_frame_ly->addWidget (mp_cpy_label);
cp_frame_ly->insertSpacing (-1, 6);
// connect to the menus to provide the dynamic parts
QMenu *bookmark_menu = mp_menu->menu ("bookmark_menu");
tl_assert (bookmark_menu != 0);
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
// select the default mode
select_mode (lay::LayoutView::default_mode ());
@ -1798,6 +1793,12 @@ MainWindow::edits_enabled_changed ()
}
}
void
MainWindow::menu_needs_update ()
{
lay::LayoutView::update_menu (current_view (), *mp_menu);
}
void
MainWindow::libraries_changed ()
{
@ -2426,57 +2427,6 @@ MainWindow::cm_redo ()
END_PROTECTED
}
void
MainWindow::bookmark_menu_show ()
{
if (mp_menu->is_valid ("bookmark_menu.goto_bookmark_menu")) {
Action goto_bookmark_action = mp_menu->action ("bookmark_menu.goto_bookmark_menu");
bool has_bookmarks = current_view () && current_view ()->bookmarks ().size () > 0;
if (has_bookmarks && edits_enabled ()) {
goto_bookmark_action.set_enabled (true);
QMenu *goto_bookmark_menu = goto_bookmark_action.qaction ()->menu ();
if (goto_bookmark_menu) {
goto_bookmark_menu->clear ();
if (current_view ()) {
const lay::BookmarkList &bookmarks = current_view ()->bookmarks ();
for (size_t i = 0; i < bookmarks.size (); ++i) {
QAction *action = goto_bookmark_menu->addAction (tl::to_qstring (bookmarks.name (i)));
action->setObjectName (tl::to_qstring (tl::sprintf ("bookmark_%d", i + 1)));
gtf::action_connect (action, SIGNAL (triggered ()), this, SLOT (goto_bookmark ()));
action->setData (QVariant (int (i)));
}
}
}
} else {
goto_bookmark_action.set_enabled (false);
}
}
}
void
MainWindow::goto_bookmark ()
{
BEGIN_PROTECTED
QAction *action = dynamic_cast <QAction *> (sender ());
tl_assert (action);
size_t id = size_t (action->data ().toInt ());
if (current_view () && current_view ()->bookmarks ().size () > id) {
current_view ()->goto_view (current_view ()->bookmarks ().state (id));
}
END_PROTECTED
}
void
MainWindow::cm_goto_position ()
{
@ -2580,19 +2530,7 @@ MainWindow::cm_bookmark_view ()
BEGIN_PROTECTED
if (current_view ()) {
while (true) {
bool ok = false;
QString text = QInputDialog::getText (this, QObject::tr ("Enter Bookmark Name"), QObject::tr ("Bookmark name"),
QLineEdit::Normal, QString::null, &ok);
if (! ok) {
break;
} else if (text.isEmpty ()) {
QMessageBox::critical (this, QObject::tr ("Error"), QObject::tr ("Enter a name for the bookmark"));
} else {
current_view ()->bookmark_view (tl::to_string (text));
break;
}
}
current_view ()->bookmark_current_view ();
}
END_PROTECTED
@ -3359,6 +3297,7 @@ MainWindow::select_view (int index)
clear_current_pos ();
edits_enabled_changed ();
clear_message ();
menu_needs_update ();
m_disable_tab_selected = dis;
@ -3738,6 +3677,7 @@ MainWindow::clone_current_view ()
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ()));
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));
@ -4041,6 +3981,7 @@ MainWindow::close_view (int index)
clear_current_pos ();
edits_enabled_changed ();
menu_needs_update ();
clear_message ();
update_dock_widget_state ();
@ -4184,10 +4125,7 @@ MainWindow::do_update_file_menu ()
if (m_mru.size () > 0 && edits_enabled ()) {
// rebuild MRU menu
std::vector<std::string> items = mp_menu->items (mru_menu);
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
mp_menu->delete_item (mru_menu + "." + *i);
}
mp_menu->clear_menu (mru_menu);
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
--mru;
@ -4349,6 +4287,7 @@ MainWindow::do_create_view ()
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ()));
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));

View File

@ -689,7 +689,6 @@ public slots:
void tab_close_requested (int);
void enable_all ();
void disable_all ();
void goto_bookmark ();
void open_recent ();
void view_selected (int index);
void view_title_changed ();
@ -858,8 +857,9 @@ public slots:
protected slots:
void menu_changed ();
void message_timer ();
void bookmark_menu_show ();
void edits_enabled_changed ();
void menu_needs_update ();
void file_changed_timer ();
void file_changed (const QString &path);
void file_removed (const QString &path);
@ -874,7 +874,6 @@ private:
// Main menu
AbstractMenu *mp_menu;
QMenu *mp_goto_bookmark_menu;
QTabBar *mp_tab_bar;
QToolBar *mp_tool_bar;
QDockWidget *mp_navigator_dock_widget;

View File

@ -1354,6 +1354,17 @@ AbstractMenu::insert_menu (const std::string &path, const std::string &name, con
insert_menu (path, name, create_action (title));
}
void
AbstractMenu::clear_menu (const std::string &p)
{
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
path_type path = find_item (p);
if (! path.empty () && ! path.back ().second->children.empty ()) {
path.back ().second->children.clear ();
emit changed ();
}
}
void
AbstractMenu::delete_item (const std::string &p)
{

View File

@ -784,6 +784,13 @@ public:
*/
void insert_menu (const std::string &path, const std::string &name, const std::string &title);
/**
* @brief Deletes the children of the item with the given path
*
* If the item does not exist or is not a menu, this method does nothing.
*/
void clear_menu (const std::string &path);
/**
* @brief Delete the item given by the path
*

View File

@ -42,6 +42,7 @@
#include "tlString.h"
#include "tlLog.h"
#include "tlAssert.h"
#include "tlExceptions.h"
#include "layLayoutView.h"
#include "layViewOp.h"
#include "layViewObject.h"
@ -74,6 +75,7 @@
#include "rdbMarkerBrowserDialog.h"
#include "tlXMLParser.h"
#include "gsi.h"
#include "gtf.h"
#include <limits>
@ -772,6 +774,37 @@ LayoutView::init_menu (lay::AbstractMenu &menu)
lay::HierarchyControlPanel::init_menu (menu);
}
void
LayoutView::update_menu (lay::LayoutView *view, lay::AbstractMenu &menu)
{
std::string bm_menu = "bookmark_menu.goto_bookmark_menu";
if (menu.is_valid (bm_menu)) {
menu.clear_menu (bm_menu);
Action goto_bookmark_action = menu.action (bm_menu);
if (view && view->bookmarks ().size () > 0) {
goto_bookmark_action.set_enabled (true);
const lay::BookmarkList &bookmarks = view->bookmarks ();
for (size_t i = 0; i < bookmarks.size (); ++i) {
Action action;
gtf::action_connect (action.qaction (), SIGNAL (triggered ()), view, SLOT (goto_bookmark ()));
action.set_title (bookmarks.name (i));
action.qaction ()->setData (QVariant (int (i)));
menu.insert_item (bm_menu + ".end", tl::sprintf ("bookmark_%d", i + 1), action);
}
} else {
goto_bookmark_action.set_enabled (false);
}
}
}
void
LayoutView::set_drawing_workers (int workers)
{
@ -3650,6 +3683,24 @@ LayoutView::cancel ()
clear_selection ();
}
void
LayoutView::bookmark_current_view ()
{
while (true) {
bool ok = false;
QString text = QInputDialog::getText (this, QObject::tr ("Enter Bookmark Name"), QObject::tr ("Bookmark name"),
QLineEdit::Normal, QString::null, &ok);
if (! ok) {
break;
} else if (text.isEmpty ()) {
QMessageBox::critical (this, QObject::tr ("Error"), QObject::tr ("Enter a name for the bookmark"));
} else {
bookmark_view (tl::to_string (text));
break;
}
}
}
void
LayoutView::manage_bookmarks ()
{
@ -3663,6 +3714,7 @@ void
LayoutView::bookmarks (const BookmarkList &b)
{
m_bookmarks = b;
emit menu_needs_update ();
}
void
@ -3670,6 +3722,22 @@ LayoutView::bookmark_view (const std::string &name)
{
DisplayState state (box (), get_min_hier_levels (), get_max_hier_levels (), m_cellviews);
m_bookmarks.add (name, state);
emit menu_needs_update ();
}
void
LayoutView::goto_bookmark ()
{
BEGIN_PROTECTED
QAction *action = dynamic_cast <QAction *> (sender ());
tl_assert (action);
size_t id = size_t (action->data ().toInt ());
if (bookmarks ().size () > id) {
goto_view (bookmarks ().state (id));
}
END_PROTECTED
}
void

View File

@ -1557,6 +1557,11 @@ public:
*/
void bookmark_view (const std::string &name);
/**
* @brief Asks for a bookmark name and bookmark the current view under this name
*/
void bookmark_current_view ();
/**
* @brief Show the bookmark management form
*/
@ -1603,6 +1608,12 @@ public:
*/
static void init_menu (lay::AbstractMenu &menu);
/**
* @brief Updates the menu for the given view
* If the view is 0, the menu shall be updated to reflect "no view active"
*/
static void update_menu (lay::LayoutView *view, lay::AbstractMenu &menu);
/**
* @brief Query the default mode
*/
@ -2530,6 +2541,7 @@ public slots:
private slots:
void active_cellview_changed (int index);
void goto_bookmark ();
signals:
/**
@ -2562,6 +2574,11 @@ signals:
*/
void edits_enabled_changed ();
/**
* @brief This signal is sent when the view wants to update the menu
*/
void menu_needs_update ();
protected:
/**
* @brief Establish the view operations

View File

@ -124,5 +124,14 @@ TEST(1)
menu.delete_item ("n1.c2");
EXPECT_EQ (menu_to_string (menu), "(n2)");
}
menu.clear_menu ("n1");
EXPECT_EQ (menu_to_string (menu), "(n2)");
menu.insert_menu ("end", "n1", lay::Action ("title:n1"));
menu.insert_item ("n1.begin", "c1", lay::Action ("title:c1"));
menu.insert_item ("n1.end", "c2", lay::Action ("title:c2"));
EXPECT_EQ (menu_to_string (menu), "(n2,n1(n1.c1,n1.c2))");
menu.clear_menu ("n1");
EXPECT_EQ (menu_to_string (menu), "(n2,n1)");
}