/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include Qt5Menu::Qt5Menu(bool bMenuBar) : mpVCLMenu(nullptr) , mpParentSalMenu(nullptr) , mpFrame(nullptr) , mbMenuBar(bMenuBar) { } Qt5Menu::~Qt5Menu() { maItems.clear(); } bool Qt5Menu::VisibleMenuBar() { return true; } void Qt5Menu::InsertItem(SalMenuItem* pSalMenuItem, unsigned nPos) { SolarMutexGuard aGuard; Qt5MenuItem* pItem = static_cast(pSalMenuItem); if (nPos == MENU_APPEND) maItems.push_back(pItem); else maItems.insert(maItems.begin() + nPos, pItem); pItem->mpParentMenu = this; } void Qt5Menu::RemoveItem(unsigned nPos) { SolarMutexGuard aGuard; maItems.erase(maItems.begin() + nPos); } void Qt5Menu::SetSubMenu(SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned) { SolarMutexGuard aGuard; Qt5MenuItem* pItem = static_cast(pSalMenuItem); Qt5Menu* pQSubMenu = static_cast(pSubMenu); if (pQSubMenu == nullptr) return; pQSubMenu->mpParentSalMenu = this; pItem->mpSubMenu = pQSubMenu; } void Qt5Menu::SetFrame(const SalFrame* pFrame) { SolarMutexGuard aGuard; assert(mbMenuBar); mpFrame = const_cast(static_cast(pFrame)); mpFrame->SetMenu(this); Qt5MainWindow* pMainWindow = mpFrame->GetTopLevelWindow(); if (pMainWindow) mpQMenuBar = pMainWindow->menuBar(); DoFullMenuUpdate(mpVCLMenu); } void Qt5Menu::DoFullMenuUpdate(Menu* pMenuBar, QMenu* pParentMenu) { Menu* pVCLMenu = mpVCLMenu; if (mbMenuBar && mpQMenuBar) mpQMenuBar->clear(); QActionGroup* pQAG = nullptr; for (sal_Int32 nItem = 0; nItem < static_cast(GetItemCount()); nItem++) { Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem); sal_uInt16 nId = pSalMenuItem->mnId; OUString aText = pVCLMenu->GetItemText(nId); QMenu* pQMenu = pParentMenu; NativeItemText(aText); vcl::KeyCode nAccelKey = pVCLMenu->GetAccelKey(nId); bool bChecked = pVCLMenu->IsItemChecked(nId); MenuItemBits itemBits = pVCLMenu->GetItemBits(nId); if (mbMenuBar && mpQMenuBar) // top-level menu pQMenu = mpQMenuBar->addMenu(toQString(aText)); else { if (pSalMenuItem->mpSubMenu) { // submenu pQMenu = pQMenu->addMenu(toQString(aText)); pQAG = new QActionGroup(pQMenu); } else { if (pSalMenuItem->mnType == MenuItemType::SEPARATOR) pQMenu->addSeparator(); else { // leaf menu QAction* pAction = pQMenu->addAction(toQString(aText)); pSalMenuItem->mpAction = pAction; pAction->setShortcut(toQString(nAccelKey.GetName(GetFrame()->GetWindow()))); if (itemBits & MenuItemBits::CHECKABLE) { pAction->setCheckable(true); pAction->setChecked(bChecked); } else if (itemBits & MenuItemBits::RADIOCHECK) { pAction->setCheckable(true); if (!pQAG) { pQAG = new QActionGroup(pQMenu); pQAG->setExclusive(true); } pQAG->addAction(pAction); pAction->setChecked(bChecked); } pAction->setEnabled(pSalMenuItem->mbEnabled); pAction->setVisible(pSalMenuItem->mbVisible); connect(pAction, &QAction::triggered, this, [this, pSalMenuItem] { slotMenuTriggered(pSalMenuItem); }); } } } if (pSalMenuItem->mpSubMenu != nullptr) { pMenuBar->HandleMenuActivateEvent(pSalMenuItem->mpSubMenu->GetMenu()); pSalMenuItem->mpSubMenu->DoFullMenuUpdate(pMenuBar, pQMenu); pMenuBar->HandleMenuDeActivateEvent(pSalMenuItem->mpSubMenu->GetMenu()); } } } void Qt5Menu::ShowItem(unsigned nPos, bool bShow) { if (nPos < maItems.size()) { Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setVisible(bShow); pSalMenuItem->mbVisible = bShow; } } void Qt5Menu::CheckItem(unsigned nPos, bool bChecked) { if (nPos < maItems.size()) { Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setChecked(bChecked); } } void Qt5Menu::EnableItem(unsigned nPos, bool bEnable) { if (nPos < maItems.size()) { Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setEnabled(bEnable); pSalMenuItem->mbEnabled = bEnable; } } void Qt5Menu::SetItemText(unsigned, SalMenuItem* pItem, const OUString& rText) { Qt5MenuItem* pSalMenuItem = static_cast(pItem); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setText(toQString(rText)); } void Qt5Menu::SetItemImage(unsigned, SalMenuItem* pItem, const Image& rImage) { BitmapEx aBmpEx(rImage.GetBitmapEx()); Bitmap aBmp(aBmpEx.GetBitmap()); if (!aBmp || !aBmp.ImplGetSalBitmap()) return; // simple case, no transparency Qt5MenuItem* pSalMenuItem = static_cast(pItem); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setIcon(QPixmap::fromImage( *static_cast(aBmp.ImplGetSalBitmap().get())->GetQImage())); } void Qt5Menu::SetAccelerator(unsigned, SalMenuItem* pItem, const vcl::KeyCode&, const OUString& rText) { Qt5MenuItem* pSalMenuItem = static_cast(pItem); if (pSalMenuItem->mpAction) pSalMenuItem->mpAction->setShortcut( QKeySequence(toQString(rText), QKeySequence::PortableText)); } void Qt5Menu::GetSystemMenuData(SystemMenuData*) {} Qt5Menu* Qt5Menu::GetTopLevel() { Qt5Menu* pMenu = this; while (pMenu->mpParentSalMenu) pMenu = pMenu->mpParentSalMenu; return pMenu; } const Qt5Frame* Qt5Menu::GetFrame() const { SolarMutexGuard aGuard; const Qt5Menu* pMenu = this; while (pMenu && !pMenu->mpFrame) pMenu = pMenu->mpParentSalMenu; return pMenu ? pMenu->mpFrame : nullptr; } void Qt5Menu::slotMenuTriggered(Qt5MenuItem* pQItem) { if (pQItem) { Qt5Menu* pSalMenu = pQItem->mpParentMenu; Qt5Menu* pTopLevel = pSalMenu->GetTopLevel(); // it is possible that dispatcher of a menu entry was cleared since // initial activation (happens e.g. when extension comes w/ its own menus // and dispatchers) so re-activate the entry before dispatching the command pTopLevel->GetMenu()->HandleMenuActivateEvent(pSalMenu->GetMenu()); pTopLevel->GetMenu()->HandleMenuCommandEvent(pSalMenu->GetMenu(), pQItem->mnId); } } void Qt5Menu::NativeItemText(OUString& rItemText) { // preserve literal '&'s in menu texts rItemText = rItemText.replaceAll("&", "&&"); rItemText = rItemText.replace('~', '&'); } Qt5MenuItem::Qt5MenuItem(const SalItemParams* pItemData) : mpParentMenu(nullptr) , mpSubMenu(nullptr) , mpAction(nullptr) , mnId(pItemData->nId) , mnType(pItemData->eType) , mbVisible(true) , mbEnabled(true) { } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */