PDA

View Full Version : QT: MAC menu shared among multiple QWidgets only triggers MainWindow's functions



LucaDanieli
10th March 2017, 22:18
I have an application generally structured as the following:


class MultiEditor : public QWidget
{
...
MultiSplitter *mSplitter;
...
}

MultiEditor::MultiEditor( Main *main, QWidget * parent )
{
...
mActions[SplitHorizontally] = action = new QAction(tr("Split To Right"), this);
action->setShortcut( tr("Ctrl+P, 3", "Split To Right"));
connect(action, SIGNAL(triggered()), this, SLOT(splitHorizontally()));
settings->addAction( action, "editor-split-right", editorCategory);
...
}

void MultiEditor::splitHorizontally()
{
... do something on &mSplitter (above);
}


and a class MainWindow:


MainWindow::MainWindow(Main * main)
{
...
mEditors = new MultiEditor(main);
setCurrentMultiEditor(mEditors);
...
createActions();
mMenu = createMenus();
this->setMenuBar(mMenu);
...
}


and a class SubWindow that creates a widget:


SubWindow::SubWindow( QVariant * splitterData = 0, QWidget * parent = 0 )
{
...
sEditors = new MultiEditor(Main::instance(), this);
setCurrentMultiEditor(sEditors);
...
#ifndef Q_OS_MAC
QMenuBar *newMenu = main->createMenus();
newMenu->setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Fixed );
windowLayout->addWidget(newMenu);
#endif
...
}


and the actual menu constructor:


QMenuBar * MainWindow::createMenus()
{
QMenuBar *menuBar;
QMenu *menu;
QMenu *submenu;
...
#ifdef Q_OS_MAC
menuBar = new QMenuBar(0);
#else
menuBar = new QMenuBar();
#endif
...
menu->addAction( currentMultiEditor()->action(MultiEditor::SplitHorizontally) );
...
return menuBar;
}


Let's suppose that I have the MainWindow and a open SubWindow. Both create a MultiEditor with a Splitter inside. All this works good on Ubuntu: every action is associated with the right Splitter. If I click on the SubWindow's Splitter, for example, and I trigger the action "splitHorizontally", the SubWindow's MultiEditor:splitHorizontally() is triggered, and the SubWindow's Splitter is affected.

This does not happen on Mac. Here, if I click on a SubWindow's Splitter, the mSplitter of the MainWindow is affected. I believed that clicking on a mSplitter, I would focus that mSplitter, so the MAC's parentless menu would act on whatever mSplitter focused. But it happens that it get stucked with the mSplitter on the MainWindow.

Actually, could it be that I was thinking that the function currentMultiEditor() was dynamic (every time the action was triggered, a different MultiEditor was called), but in the truth the multiEditor is fixed when creating the menu (in MAC the menu is created only on the MainWindow, so the currentMultiEditor() would be MainWindow's mEditors, and that would still be anytime the action were triggered from anywhere)?

What is the best design for you? Should I create new menus on MAC too? How?

anda_skoa
11th March 2017, 10:46
I am not sure I understand your setup, but if you have one set of actions that can apply to any of multiple widgets, then the slots need to know which which widget to affect.

How to you track that currently?

Cheers,
_

LucaDanieli
17th March 2017, 18:10
Super-thank you, anda_skoa

well, I have a currentMultiEditor() function that gives me the focused editor.
It works fine in Linux, and every time I build a new widget (window), I re-set my currentMultiEditor() manually (meaning: I run explicitly a setCurrentMultiEditor() function).

Still, on MAC, the action is working on one only widget (the MainWindow (the first widget created)), so I don't understand if the menu retrieve the currentMultiEditor() only when it is built, or if it runs the function every time).

Particularly, in the beginning currentMultiEditor() is an instance called mEditors.
The following widget (created later) is called sEditors.

So, when creating the menu in MAC, the currentMultiEditor() == mEditors.
After I create a new widget (window), I setCurrentMultiEditor(sEditors), I call the action, and the action modifies mEditor again.

anda_skoa
18th March 2017, 09:16
so I don't understand if the menu retrieve the currentMultiEditor() only when it is built, or if it runs the function every time).

This is C++, the function is called whenever the thread executing the code reaches its invocation.

Your code snippets show one call in MainWindow::createMenus(), so it is called when createMenus() is called.

If you also call it in the slots connected to the actions, then it is also called when the actions are triggered.

Cheers,
_

LucaDanieli
18th March 2017, 10:33
Thank you!
You are saving the day.

So basically, I have to update the menu (re-creating it) whenever a new widget is focused?
Do you think that that would be a good design?

anda_skoa
22nd March 2017, 08:50
Depends on your needs.

You could also have a single menu and switch in the slots.

Cheers,
_