diff options
author | Aleksei Nikiforov <darktemplar@basealt.ru> | 2019-01-11 16:39:55 +0300 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2019-01-16 22:41:18 +0100 |
commit | aa3ef0a5efa3da3fe1d06509af52fe46fe8c6c81 (patch) | |
tree | daafe3e6444f6cf74381fc747eb35d2ca09bb97c /vcl/qt5/Qt5Menu.cxx | |
parent | f9231f054e5b6597ae8a92da165a1841e4199378 (diff) |
KDE5: Fix radiocheck menu items
This change fixes displaying of elements of 'Styles' menu of Writer
Change-Id: I455a4f1c37aa7bc6641ebdd15eec23f18a8430d9
Reviewed-on: https://gerrit.libreoffice.org/66387
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'vcl/qt5/Qt5Menu.cxx')
-rw-r--r-- | vcl/qt5/Qt5Menu.cxx | 163 |
1 files changed, 150 insertions, 13 deletions
diff --git a/vcl/qt5/Qt5Menu.cxx b/vcl/qt5/Qt5Menu.cxx index ceaf0d9138f9..8fee56a9cf70 100644 --- a/vcl/qt5/Qt5Menu.cxx +++ b/vcl/qt5/Qt5Menu.cxx @@ -27,7 +27,6 @@ Qt5Menu::Qt5Menu(bool bMenuBar) , mbMenuBar(bMenuBar) , mpQMenuBar(nullptr) , mpQMenu(nullptr) - , mpQActionGroup(nullptr) { connect(this, &Qt5Menu::setFrameSignal, this, &Qt5Menu::SetFrame, Qt::BlockingQueuedConnection); } @@ -90,7 +89,11 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) } pQMenu = pTempQMenu; - mpQActionGroup = new QActionGroup(pQMenu); + + ReinitializeActionGroup(nPos); + + // clear all action groups since menu is recreated + pSalMenuItem->mpSubMenu->ResetAllActionGroups(); connect(pQMenu, &QMenu::aboutToShow, this, [pSalMenuItem] { slotMenuAboutToShow(pSalMenuItem); }); @@ -114,6 +117,8 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) { pQMenu->addAction(pAction); } + + ReinitializeActionGroup(nPos); } else { @@ -131,6 +136,8 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) pQMenu->addAction(pAction); } + ReinitializeActionGroup(nPos); + pAction->setShortcut(toQString(nAccelKey.GetName(GetFrame()->GetWindow()))); if (itemBits & MenuItemBits::CHECKABLE) @@ -141,15 +148,12 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) else if (itemBits & MenuItemBits::RADIOCHECK) { pAction->setCheckable(true); - if (!mpQActionGroup) + + if (pSalMenuItem->mpActionGroup) { - mpQActionGroup = new QActionGroup(pQMenu); - mpQActionGroup->setExclusive(true); + pSalMenuItem->mpActionGroup->addAction(pAction); } - // NOTE: QActionGroup support may need improvement - // if menu item is added not to the end of menu, - // it may be needed to add new item to QActionGroup different from last created one for this menu - mpQActionGroup->addAction(pAction); + pAction->setChecked(bChecked); } @@ -165,6 +169,130 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) return pQMenu; } +void Qt5Menu::ReinitializeActionGroup(unsigned nPos) +{ + const unsigned nCount = GetItemCount(); + + if (nCount == 0) + { + return; + } + + if (nPos == MENU_APPEND) + { + nPos = nCount - 1; + } + else if (nPos >= nCount) + { + return; + } + + Qt5MenuItem* pPrevItem = (nPos > 0) ? GetItemAtPos(nPos - 1) : nullptr; + Qt5MenuItem* pCurrentItem = GetItemAtPos(nPos); + Qt5MenuItem* pNextItem = (nPos < nCount - 1) ? GetItemAtPos(nPos + 1) : nullptr; + + if (pCurrentItem->mnType == MenuItemType::SEPARATOR) + { + pCurrentItem->mpActionGroup.reset(); + + // if it's inserted into middle of existing group, split it into two groups: + // first goes original group, after separator goes new group + if (pPrevItem && pPrevItem->mpActionGroup && pNextItem && pNextItem->mpActionGroup + && (pPrevItem->mpActionGroup == pNextItem->mpActionGroup)) + { + std::shared_ptr<QActionGroup> pFirstActionGroup = pPrevItem->mpActionGroup; + std::shared_ptr<QActionGroup> pSecondActionGroup(new QActionGroup(nullptr)); + pSecondActionGroup->setExclusive(true); + + auto actions = pFirstActionGroup->actions(); + + for (unsigned idx = nPos + 1; idx < nCount; ++idx) + { + Qt5MenuItem* pModifiedItem = GetItemAtPos(idx); + + if ((!pModifiedItem) || (!pModifiedItem->mpActionGroup)) + { + break; + } + + pModifiedItem->mpActionGroup = pSecondActionGroup; + auto action = pModifiedItem->getAction(); + + if (actions.contains(action)) + { + pFirstActionGroup->removeAction(action); + pSecondActionGroup->addAction(action); + } + } + } + } + else + { + if (!pCurrentItem->mpActionGroup) + { + // unless element is inserted between two separators, or a separator and an end of vector, use neighbouring group since it's shared + if (pPrevItem && pPrevItem->mpActionGroup) + { + pCurrentItem->mpActionGroup = pPrevItem->mpActionGroup; + } + else if (pNextItem && pNextItem->mpActionGroup) + { + pCurrentItem->mpActionGroup = pNextItem->mpActionGroup; + } + else + { + pCurrentItem->mpActionGroup.reset(new QActionGroup(nullptr)); + pCurrentItem->mpActionGroup->setExclusive(true); + } + } + + // if there's also a different group after this element, merge it + if (pNextItem && pNextItem->mpActionGroup + && (pCurrentItem->mpActionGroup != pNextItem->mpActionGroup)) + { + auto pFirstCheckedAction = pCurrentItem->mpActionGroup->checkedAction(); + auto pSecondCheckedAction = pNextItem->mpActionGroup->checkedAction(); + auto actions = pNextItem->mpActionGroup->actions(); + + // first move all actions from second group to first one, and if first group already has checked action, + // and second group also has a checked action, uncheck action from second group + for (auto action : actions) + { + pNextItem->mpActionGroup->removeAction(action); + + if (pFirstCheckedAction && pSecondCheckedAction && (action == pSecondCheckedAction)) + { + action->setChecked(false); + } + + pCurrentItem->mpActionGroup->addAction(action); + } + + // now replace all pointers to second group with pointers to first group + for (unsigned idx = nPos + 1; idx < nCount; ++idx) + { + Qt5MenuItem* pModifiedItem = GetItemAtPos(idx); + + if ((!pModifiedItem) || (!pModifiedItem->mpActionGroup)) + { + break; + } + + pModifiedItem->mpActionGroup = pCurrentItem->mpActionGroup; + } + } + } +} + +void Qt5Menu::ResetAllActionGroups() +{ + for (unsigned nItem = 0; nItem < GetItemCount(); ++nItem) + { + Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem); + pSalMenuItem->mpActionGroup.reset(); + } +} + void Qt5Menu::InsertItem(SalMenuItem* pSalMenuItem, unsigned nPos) { SolarMutexGuard aGuard; @@ -191,6 +319,14 @@ void Qt5Menu::RemoveItem(unsigned nPos) pItem->mpMenu.reset(); maItems.erase(maItems.begin() + nPos); + + // Recalculate action groups if necessary: + // if separator between two QActionGroups was removed, + // it may be needed to merge them + if (nPos > 0) + { + ReinitializeActionGroup(nPos - 1); + } } } @@ -229,7 +365,6 @@ void Qt5Menu::SetFrame(const SalFrame* pFrame) mpQMenuBar->clear(); mpQMenu = nullptr; - mpQActionGroup = nullptr; DoFullMenuUpdate(mpVCLMenu); } @@ -237,17 +372,19 @@ void Qt5Menu::SetFrame(const SalFrame* pFrame) void Qt5Menu::DoFullMenuUpdate(Menu* pMenuBar) { + // clear action groups since menu is rebuilt + ResetAllActionGroups(); + for (sal_Int32 nItem = 0; nItem < static_cast<sal_Int32>(GetItemCount()); nItem++) { Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem); - QMenu* pQMenu = InsertMenuItem(pSalMenuItem, MENU_APPEND); + QMenu* pQMenu = InsertMenuItem(pSalMenuItem, nItem); SetItemImage(nItem, pSalMenuItem, pSalMenuItem->maImage); if (pSalMenuItem->mpSubMenu != nullptr) { - // correct parent menu and action group before calling HandleMenuActivateEvent + // correct parent menu before calling HandleMenuActivateEvent pSalMenuItem->mpSubMenu->mpQMenu = pQMenu; - pSalMenuItem->mpSubMenu->mpQActionGroup = nullptr; pMenuBar->HandleMenuActivateEvent(pSalMenuItem->mpSubMenu->GetMenu()); pSalMenuItem->mpSubMenu->DoFullMenuUpdate(pMenuBar); |