Kaydet (Commit) cb37c789 authored tarafından Aleksei Nikiforov's avatar Aleksei Nikiforov Kaydeden (comit) Katarina Behrens

tdf#120814 KDE5: Assign images to menu items on first build of menu

Treat submenu items similarly to action items.

Qt5MenuItem controls lifetime of menus and actions instead of QMenu or QMenuBar.
Qt5MenuItem may need to remove menus, and thus it may need to delete it.
But if QMenu or QMenuBar owns menu, then on application exit a crash may happen
due to order of destruction of objects.

Change-Id: I66138c5692bd4955e78a805cc774ff9fc8fefb99
Reviewed-on: https://gerrit.libreoffice.org/63886
Tested-by: Jenkins
Reviewed-by: 's avatarKatarina Behrens <Katarina.Behrens@cib.de>
üst bc0146c2
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <salmenu.hxx> #include <salmenu.hxx>
#include <memory>
class MenuItemList; class MenuItemList;
class QActionGroup; class QActionGroup;
class QMenu; class QMenu;
...@@ -77,15 +79,18 @@ class Qt5MenuItem : public SalMenuItem ...@@ -77,15 +79,18 @@ class Qt5MenuItem : public SalMenuItem
{ {
public: public:
Qt5MenuItem(const SalItemParams*); Qt5MenuItem(const SalItemParams*);
virtual ~Qt5MenuItem() override;
QAction* getAction() const;
Qt5Menu* mpParentMenu; // The menu into which this menu item is inserted Qt5Menu* mpParentMenu; // The menu into which this menu item is inserted
Qt5Menu* mpSubMenu; // Submenu of this item (if defined) Qt5Menu* mpSubMenu; // Submenu of this item (if defined)
QAction* mpAction; // action corresponding to this item std::unique_ptr<QAction> mpAction; // action corresponding to this item
std::unique_ptr<QMenu> mpMenu; // menu corresponding to this item
sal_uInt16 mnId; // Item ID sal_uInt16 mnId; // Item ID
MenuItemType mnType; // Item type MenuItemType mnType; // Item type
bool mbVisible; // Item visibility. bool mbVisible; // Item visibility.
bool mbEnabled; // Item active. bool mbEnabled; // Item active.
Image maImage; // Item image
}; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <Qt5Frame.hxx> #include <Qt5Frame.hxx>
#include <Qt5MainWindow.hxx> #include <Qt5MainWindow.hxx>
#include <Qt5Bitmap.hxx> #include <Qt5Bitmap.hxx>
#include <Qt5Tools.hxx>
#include <Qt5Menu.hxx> #include <Qt5Menu.hxx>
#include <Qt5Menu.moc> #include <Qt5Menu.moc>
...@@ -47,20 +46,25 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) ...@@ -47,20 +46,25 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos)
bool bChecked = mpVCLMenu->IsItemChecked(nId); bool bChecked = mpVCLMenu->IsItemChecked(nId);
MenuItemBits itemBits = mpVCLMenu->GetItemBits(nId); MenuItemBits itemBits = mpVCLMenu->GetItemBits(nId);
pSalMenuItem->mpAction.reset();
pSalMenuItem->mpMenu.reset();
if (mbMenuBar) if (mbMenuBar)
{ {
// top-level menu // top-level menu
if (mpQMenuBar) if (mpQMenuBar)
{ {
pQMenu = new QMenu(toQString(aText));
pSalMenuItem->mpMenu.reset(pQMenu);
if ((nPos != MENU_APPEND) if ((nPos != MENU_APPEND)
&& (static_cast<size_t>(nPos) < static_cast<size_t>(mpQMenuBar->actions().size()))) && (static_cast<size_t>(nPos) < static_cast<size_t>(mpQMenuBar->actions().size())))
{ {
pQMenu = new QMenu(toQString(aText), mpQMenuBar);
mpQMenuBar->insertMenu(mpQMenuBar->actions()[nPos], pQMenu); mpQMenuBar->insertMenu(mpQMenuBar->actions()[nPos], pQMenu);
} }
else else
{ {
pQMenu = mpQMenuBar->addMenu(toQString(aText)); mpQMenuBar->addMenu(pQMenu);
} }
connect(pQMenu, &QMenu::aboutToShow, this, connect(pQMenu, &QMenu::aboutToShow, this,
...@@ -74,18 +78,20 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) ...@@ -74,18 +78,20 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos)
if (pSalMenuItem->mpSubMenu) if (pSalMenuItem->mpSubMenu)
{ {
// submenu // submenu
QMenu* pTempQMenu = new QMenu(toQString(aText));
pSalMenuItem->mpMenu.reset(pTempQMenu);
if ((nPos != MENU_APPEND) if ((nPos != MENU_APPEND)
&& (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size()))) && (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size())))
{ {
QMenu* pTempQMenu = new QMenu(toQString(aText), pQMenu);
pQMenu->insertMenu(pQMenu->actions()[nPos], pTempQMenu); pQMenu->insertMenu(pQMenu->actions()[nPos], pTempQMenu);
pQMenu = pTempQMenu;
} }
else else
{ {
pQMenu = pQMenu->addMenu(toQString(aText)); pQMenu->addMenu(pTempQMenu);
} }
pQMenu = pTempQMenu;
mpQActionGroup = new QActionGroup(pQMenu); mpQActionGroup = new QActionGroup(pQMenu);
connect(pQMenu, &QMenu::aboutToShow, this, connect(pQMenu, &QMenu::aboutToShow, this,
...@@ -95,37 +101,38 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos) ...@@ -95,37 +101,38 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos)
} }
else else
{ {
delete pSalMenuItem->mpAction;
if (pSalMenuItem->mnType == MenuItemType::SEPARATOR) if (pSalMenuItem->mnType == MenuItemType::SEPARATOR)
{ {
QAction* pAction = new QAction();
pSalMenuItem->mpAction.reset(pAction);
pAction->setSeparator(true);
if ((nPos != MENU_APPEND) if ((nPos != MENU_APPEND)
&& (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size()))) && (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size())))
{ {
pSalMenuItem->mpAction = pQMenu->insertSeparator(pQMenu->actions()[nPos]); pQMenu->insertAction(pQMenu->actions()[nPos], pAction);
} }
else else
{ {
pSalMenuItem->mpAction = pQMenu->addSeparator(); pQMenu->addAction(pAction);
} }
} }
else else
{ {
// leaf menu // leaf menu
QAction* pAction = nullptr; QAction* pAction = new QAction(toQString(aText));
pSalMenuItem->mpAction.reset(pAction);
if ((nPos != MENU_APPEND) if ((nPos != MENU_APPEND)
&& (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size()))) && (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size())))
{ {
pAction = new QAction(toQString(aText), pQMenu);
pQMenu->insertAction(pQMenu->actions()[nPos], pAction); pQMenu->insertAction(pQMenu->actions()[nPos], pAction);
} }
else else
{ {
pAction = pQMenu->addAction(toQString(aText)); pQMenu->addAction(pAction);
} }
pSalMenuItem->mpAction = pAction;
pAction->setShortcut(toQString(nAccelKey.GetName(GetFrame()->GetWindow()))); pAction->setShortcut(toQString(nAccelKey.GetName(GetFrame()->GetWindow())));
if (itemBits & MenuItemBits::CHECKABLE) if (itemBits & MenuItemBits::CHECKABLE)
...@@ -229,6 +236,7 @@ void Qt5Menu::DoFullMenuUpdate(Menu* pMenuBar, QMenu* pParentMenu) ...@@ -229,6 +236,7 @@ void Qt5Menu::DoFullMenuUpdate(Menu* pMenuBar, QMenu* pParentMenu)
{ {
Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem); Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem);
QMenu* pQMenu = InsertMenuItem(pSalMenuItem, MENU_APPEND); QMenu* pQMenu = InsertMenuItem(pSalMenuItem, MENU_APPEND);
SetItemImage(nItem, pSalMenuItem, pSalMenuItem->maImage);
if (pSalMenuItem->mpSubMenu != nullptr) if (pSalMenuItem->mpSubMenu != nullptr)
{ {
...@@ -244,8 +252,9 @@ void Qt5Menu::ShowItem(unsigned nPos, bool bShow) ...@@ -244,8 +252,9 @@ void Qt5Menu::ShowItem(unsigned nPos, bool bShow)
if (nPos < maItems.size()) if (nPos < maItems.size())
{ {
Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos);
if (pSalMenuItem->mpAction) QAction* pAction = pSalMenuItem->getAction();
pSalMenuItem->mpAction->setVisible(bShow); if (pAction)
pAction->setVisible(bShow);
pSalMenuItem->mbVisible = bShow; pSalMenuItem->mbVisible = bShow;
} }
} }
...@@ -255,8 +264,9 @@ void Qt5Menu::CheckItem(unsigned nPos, bool bChecked) ...@@ -255,8 +264,9 @@ void Qt5Menu::CheckItem(unsigned nPos, bool bChecked)
if (nPos < maItems.size()) if (nPos < maItems.size())
{ {
Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos);
if (pSalMenuItem->mpAction) QAction* pAction = pSalMenuItem->getAction();
pSalMenuItem->mpAction->setChecked(bChecked); if (pAction)
pAction->setChecked(bChecked);
} }
} }
...@@ -265,8 +275,9 @@ void Qt5Menu::EnableItem(unsigned nPos, bool bEnable) ...@@ -265,8 +275,9 @@ void Qt5Menu::EnableItem(unsigned nPos, bool bEnable)
if (nPos < maItems.size()) if (nPos < maItems.size())
{ {
Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos); Qt5MenuItem* pSalMenuItem = GetItemAtPos(nPos);
if (pSalMenuItem->mpAction) QAction* pAction = pSalMenuItem->getAction();
pSalMenuItem->mpAction->setEnabled(bEnable); if (pAction)
pAction->setEnabled(bEnable);
pSalMenuItem->mbEnabled = bEnable; pSalMenuItem->mbEnabled = bEnable;
} }
} }
...@@ -274,38 +285,46 @@ void Qt5Menu::EnableItem(unsigned nPos, bool bEnable) ...@@ -274,38 +285,46 @@ void Qt5Menu::EnableItem(unsigned nPos, bool bEnable)
void Qt5Menu::SetItemText(unsigned, SalMenuItem* pItem, const OUString& rText) void Qt5Menu::SetItemText(unsigned, SalMenuItem* pItem, const OUString& rText)
{ {
Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem); Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem);
if (pSalMenuItem->mpAction) QAction* pAction = pSalMenuItem->getAction();
pSalMenuItem->mpAction->setText(toQString(rText)); if (pAction)
pAction->setText(toQString(rText));
} }
void Qt5Menu::SetItemImage(unsigned, SalMenuItem* pItem, const Image& rImage) void Qt5Menu::SetItemImage(unsigned, SalMenuItem* pItem, const Image& rImage)
{ {
if (!rImage) Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem);
// Save new image to use it in DoFullMenuUpdate
pSalMenuItem->maImage = rImage;
QAction* pAction = pSalMenuItem->getAction();
if (!pAction)
return; return;
Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem); QImage aImage;
if (pSalMenuItem->mpAction)
if (!!rImage)
{ {
SvMemoryStream aMemStm; SvMemoryStream aMemStm;
vcl::PNGWriter aWriter(rImage.GetBitmapEx()); vcl::PNGWriter aWriter(rImage.GetBitmapEx());
aWriter.Write(aMemStm); aWriter.Write(aMemStm);
QImage aImage; if (!aImage.loadFromData(static_cast<const uchar*>(aMemStm.GetData()), aMemStm.TellEnd()))
if (aImage.loadFromData(static_cast<const uchar*>(aMemStm.GetData()), aMemStm.TellEnd()))
{ {
pSalMenuItem->mpAction->setIcon(QPixmap::fromImage(aImage)); return;
} }
} }
pAction->setIcon(QPixmap::fromImage(aImage));
} }
void Qt5Menu::SetAccelerator(unsigned, SalMenuItem* pItem, const vcl::KeyCode&, void Qt5Menu::SetAccelerator(unsigned, SalMenuItem* pItem, const vcl::KeyCode&,
const OUString& rText) const OUString& rText)
{ {
Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem); Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem);
if (pSalMenuItem->mpAction) QAction* pAction = pSalMenuItem->getAction();
pSalMenuItem->mpAction->setShortcut( if (pAction)
QKeySequence(toQString(rText), QKeySequence::PortableText)); pAction->setShortcut(QKeySequence(toQString(rText), QKeySequence::PortableText));
} }
void Qt5Menu::GetSystemMenuData(SystemMenuData*) {} void Qt5Menu::GetSystemMenuData(SystemMenuData*) {}
...@@ -379,14 +398,21 @@ void Qt5Menu::NativeItemText(OUString& rItemText) ...@@ -379,14 +398,21 @@ void Qt5Menu::NativeItemText(OUString& rItemText)
Qt5MenuItem::Qt5MenuItem(const SalItemParams* pItemData) Qt5MenuItem::Qt5MenuItem(const SalItemParams* pItemData)
: mpParentMenu(nullptr) : mpParentMenu(nullptr)
, mpSubMenu(nullptr) , mpSubMenu(nullptr)
, mpAction(nullptr)
, mnId(pItemData->nId) , mnId(pItemData->nId)
, mnType(pItemData->eType) , mnType(pItemData->eType)
, mbVisible(true) , mbVisible(true)
, mbEnabled(true) , mbEnabled(true)
, maImage(pItemData->aImage)
{ {
} }
Qt5MenuItem::~Qt5MenuItem() { delete mpAction; } QAction* Qt5MenuItem::getAction() const
{
if (mpMenu)
return mpMenu->menuAction();
if (mpAction)
return mpAction.get();
return nullptr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment