Thursday, March 23, 2017

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

Leave a Comment

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?

1 Answers

Answers 1

If I understood your question correctly, this looks indeed like a focus issue and I'm not surprised Linux behaves differently than macOS.

Probably on macOS even if you open a window and click somewhere, the focus remains on the parent window, thus calling the unexpected QAction slot.

I think you have 2 options:

  • when a subwindow is open, make sure it gains the focus. Call the QWidget::setFocus() method on one of the visible widgets of the window
  • accept keystrokes only in one place and redirect them to the current context, which in other terms is your active window

Hope that helps

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment