[Libreoffice-commits] core.git: vcl/inc vcl/qt5

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Nov 23 11:27:19 UTC 2018


 vcl/inc/qt5/Qt5Menu.hxx |    5 +
 vcl/qt5/Qt5Menu.cxx     |  128 ++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 113 insertions(+), 20 deletions(-)

New commits:
commit bc023edb6a8c9d4179ce18b1f6cec990d0107201
Author:     Aleksei Nikiforov <darktemplar at basealt.ru>
AuthorDate: Thu Nov 22 12:55:06 2018 +0300
Commit:     Katarina Behrens <Katarina.Behrens at cib.de>
CommitDate: Fri Nov 23 12:26:52 2018 +0100

    tdf#121417 Allow dynamic menu changes for Qt5 and KDE5 interfaces
    
    Separate HandleMenuActivateEvent function call from HandleMenuCommandEvent function call
    since first one might update some of menus. Also add call to HandleMenuDeActivateEvent function.
    
    Delete action with Qt5MenuItem to reflect the change in actual menu.
    
    Also update underlying qt-based menu from Qt5Menu::InsertItem function.
    
    And update Qt5Menu::SetItemImage to work with different types of descendants of SalBitmap.
    This code is shared between Qt5 and KDE5 plugins, but KDE5 plugin uses SvpSalBitmap instead of Qt5Bitmap.
    New image conversion process is borrowed from GTK plugin code.
    This approach is used in order to properly process transparency channel if it's present, and it is present usually.
    
    This change also fixes tdf#120789.
    
    Change-Id: Ifdc64c3e5d80782955b52e2da8fcff4844d2dc25
    Reviewed-on: https://gerrit.libreoffice.org/63862
    Tested-by: Jenkins
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>

diff --git a/vcl/inc/qt5/Qt5Menu.hxx b/vcl/inc/qt5/Qt5Menu.hxx
index 92d2e18b9c5c..b7432a3c11e3 100644
--- a/vcl/inc/qt5/Qt5Menu.hxx
+++ b/vcl/inc/qt5/Qt5Menu.hxx
@@ -34,7 +34,7 @@ private:
     void DoFullMenuUpdate(Menu* pMenuBar, QMenu* pParentMenu = nullptr);
     static void NativeItemText(OUString& rItemText);
 
-    QMenu* InsertMenuItem(Qt5MenuItem* pSalMenuItem);
+    QMenu* InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos);
 
 public:
     Qt5Menu(bool bMenuBar);
@@ -69,12 +69,15 @@ Q_SIGNALS:
 
 private slots:
     static void slotMenuTriggered(Qt5MenuItem* pQItem);
+    static void slotMenuAboutToShow(Qt5MenuItem* pQItem);
+    static void slotMenuAboutToHide(Qt5MenuItem* pQItem);
 };
 
 class Qt5MenuItem : public SalMenuItem
 {
 public:
     Qt5MenuItem(const SalItemParams*);
+    virtual ~Qt5MenuItem();
 
     Qt5Menu* mpParentMenu; // The menu into which this menu item is inserted
     Qt5Menu* mpSubMenu; // Submenu of this item (if defined)
diff --git a/vcl/qt5/Qt5Menu.cxx b/vcl/qt5/Qt5Menu.cxx
index ed26f31f2761..15e0136b18f3 100644
--- a/vcl/qt5/Qt5Menu.cxx
+++ b/vcl/qt5/Qt5Menu.cxx
@@ -10,6 +10,7 @@
 #include <Qt5Frame.hxx>
 #include <Qt5MainWindow.hxx>
 #include <Qt5Bitmap.hxx>
+#include <Qt5Tools.hxx>
 #include <Qt5Menu.hxx>
 #include <Qt5Menu.moc>
 
@@ -17,6 +18,8 @@
 
 #include <vcl/svapp.hxx>
 #include <sal/log.hxx>
+#include <vcl/pngwrite.hxx>
+#include <tools/stream.hxx>
 
 Qt5Menu::Qt5Menu(bool bMenuBar)
     : mpVCLMenu(nullptr)
@@ -34,7 +37,7 @@ Qt5Menu::~Qt5Menu() { maItems.clear(); }
 
 bool Qt5Menu::VisibleMenuBar() { return true; }
 
-QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem)
+QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem, unsigned nPos)
 {
     QMenu* pQMenu = mpQMenu;
     sal_uInt16 nId = pSalMenuItem->mnId;
@@ -44,25 +47,73 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem)
     bool bChecked = mpVCLMenu->IsItemChecked(nId);
     MenuItemBits itemBits = mpVCLMenu->GetItemBits(nId);
 
-    if (mbMenuBar && mpQMenuBar)
+    if (mbMenuBar)
+    {
         // top-level menu
-        pQMenu = mpQMenuBar->addMenu(toQString(aText));
-    else
+        if (mpQMenuBar)
+        {
+            if ((nPos != MENU_APPEND)
+                && (static_cast<size_t>(nPos) < static_cast<size_t>(mpQMenuBar->actions().size())))
+            {
+                pQMenu = new QMenu(toQString(aText), mpQMenuBar);
+                mpQMenuBar->insertMenu(mpQMenuBar->actions()[nPos], pQMenu);
+            }
+            else
+            {
+                pQMenu = mpQMenuBar->addMenu(toQString(aText));
+            }
+
+            connect(pQMenu, &QMenu::aboutToShow, this,
+                    [pSalMenuItem] { slotMenuAboutToShow(pSalMenuItem); });
+            connect(pQMenu, &QMenu::aboutToHide, this,
+                    [pSalMenuItem] { slotMenuAboutToHide(pSalMenuItem); });
+        }
+    }
+    else if (pQMenu)
     {
         if (pSalMenuItem->mpSubMenu)
         {
             // submenu
             pQMenu = pQMenu->addMenu(toQString(aText));
             mpQActionGroup = new QActionGroup(pQMenu);
+
+            connect(pQMenu, &QMenu::aboutToShow, this,
+                    [pSalMenuItem] { slotMenuAboutToShow(pSalMenuItem); });
+            connect(pQMenu, &QMenu::aboutToHide, this,
+                    [pSalMenuItem] { slotMenuAboutToHide(pSalMenuItem); });
         }
         else
         {
+            delete pSalMenuItem->mpAction;
+
             if (pSalMenuItem->mnType == MenuItemType::SEPARATOR)
-                pQMenu->addSeparator();
+            {
+                if ((nPos != MENU_APPEND)
+                    && (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size())))
+                {
+                    pSalMenuItem->mpAction = pQMenu->insertSeparator(pQMenu->actions()[nPos]);
+                }
+                else
+                {
+                    pSalMenuItem->mpAction = pQMenu->addSeparator();
+                }
+            }
             else
             {
                 // leaf menu
-                QAction* pAction = pQMenu->addAction(toQString(aText));
+                QAction* pAction = nullptr;
+
+                if ((nPos != MENU_APPEND)
+                    && (static_cast<size_t>(nPos) < static_cast<size_t>(pQMenu->actions().size())))
+                {
+                    pAction = new QAction(toQString(aText), pQMenu);
+                    pQMenu->insertAction(pQMenu->actions()[nPos], pAction);
+                }
+                else
+                {
+                    pAction = pQMenu->addAction(toQString(aText));
+                }
+
                 pSalMenuItem->mpAction = pAction;
                 pAction->setShortcut(toQString(nAccelKey.GetName(GetFrame()->GetWindow())));
 
@@ -79,6 +130,9 @@ QMenu* Qt5Menu::InsertMenuItem(Qt5MenuItem* pSalMenuItem)
                         mpQActionGroup = new QActionGroup(pQMenu);
                         mpQActionGroup->setExclusive(true);
                     }
+                    // 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);
                 }
@@ -106,6 +160,8 @@ void Qt5Menu::InsertItem(SalMenuItem* pSalMenuItem, unsigned nPos)
         maItems.insert(maItems.begin() + nPos, pItem);
 
     pItem->mpParentMenu = this;
+
+    InsertMenuItem(pItem, nPos);
 }
 
 void Qt5Menu::RemoveItem(unsigned nPos)
@@ -161,7 +217,7 @@ void Qt5Menu::DoFullMenuUpdate(Menu* pMenuBar, QMenu* pParentMenu)
     for (sal_Int32 nItem = 0; nItem < static_cast<sal_Int32>(GetItemCount()); nItem++)
     {
         Qt5MenuItem* pSalMenuItem = GetItemAtPos(nItem);
-        QMenu* pQMenu = InsertMenuItem(pSalMenuItem);
+        QMenu* pQMenu = InsertMenuItem(pSalMenuItem, MENU_APPEND);
 
         if (pSalMenuItem->mpSubMenu != nullptr)
         {
@@ -213,17 +269,23 @@ void Qt5Menu::SetItemText(unsigned, SalMenuItem* pItem, const OUString& rText)
 
 void Qt5Menu::SetItemImage(unsigned, SalMenuItem* pItem, const Image& rImage)
 {
-    BitmapEx aBmpEx(rImage.GetBitmapEx());
-    Bitmap aBmp(aBmpEx.GetBitmap());
-
-    if (!aBmp || !aBmp.ImplGetSalBitmap())
+    if (!rImage)
         return;
 
-    // simple case, no transparency
     Qt5MenuItem* pSalMenuItem = static_cast<Qt5MenuItem*>(pItem);
     if (pSalMenuItem->mpAction)
-        pSalMenuItem->mpAction->setIcon(QPixmap::fromImage(
-            *static_cast<Qt5Bitmap*>(aBmp.ImplGetSalBitmap().get())->GetQImage()));
+    {
+        SvMemoryStream aMemStm;
+        vcl::PNGWriter aWriter(rImage.GetBitmapEx());
+        aWriter.Write(aMemStm);
+
+        QImage aImage;
+
+        if (aImage.loadFromData(static_cast<const uchar*>(aMemStm.GetData()), aMemStm.TellEnd()))
+        {
+            pSalMenuItem->mpAction->setIcon(QPixmap::fromImage(aImage));
+        }
+    }
 }
 
 void Qt5Menu::SetAccelerator(unsigned, SalMenuItem* pItem, const vcl::KeyCode&,
@@ -261,11 +323,37 @@ void Qt5Menu::slotMenuTriggered(Qt5MenuItem* 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);
+        Menu* pMenu = pSalMenu->GetMenu();
+        auto mnId = pQItem->mnId;
+
+        pTopLevel->GetMenu()->HandleMenuCommandEvent(pMenu, mnId);
+    }
+}
+
+void Qt5Menu::slotMenuAboutToShow(Qt5MenuItem* pQItem)
+{
+    if (pQItem)
+    {
+        Qt5Menu* pSalMenu = pQItem->mpSubMenu;
+        Qt5Menu* pTopLevel = pSalMenu->GetTopLevel();
+
+        Menu* pMenu = pSalMenu->GetMenu();
+
+        // following function may update the menu
+        pTopLevel->GetMenu()->HandleMenuActivateEvent(pMenu);
+    }
+}
+
+void Qt5Menu::slotMenuAboutToHide(Qt5MenuItem* pQItem)
+{
+    if (pQItem)
+    {
+        Qt5Menu* pSalMenu = pQItem->mpSubMenu;
+        Qt5Menu* pTopLevel = pSalMenu->GetTopLevel();
+
+        Menu* pMenu = pSalMenu->GetMenu();
+
+        pTopLevel->GetMenu()->HandleMenuDeActivateEvent(pMenu);
     }
 }
 
@@ -288,4 +376,6 @@ Qt5MenuItem::Qt5MenuItem(const SalItemParams* pItemData)
 {
 }
 
+Qt5MenuItem::~Qt5MenuItem() { delete mpAction; }
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list