3
votes

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
since you're going to loose your bounty points anyway, would you be so kind to accept my answer and hand the bounty over to me ? :)Massimo Callegari
you will get the bounty anyway, won't you? except if there comes a different answer and that gets accepted before the grace period ends.Darklighter
According to stackoverflow.com/help/bounty a bounty is automatically awarded after the grace period to an answer with score of 2 or higher :(Massimo Callegari
@MassimoCallegari, sorry for the late reply. I am just trying to solve the problem. Unfortunately your suggestion doesn't work.TakeMeToTheMoon

1 Answers

2
votes

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