[Libreoffice-commits] .: Branch 'feature/unitymenus' - 3 commits - vcl/inc vcl/unx

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Aug 25 14:47:24 PDT 2012


 vcl/inc/unx/gtk/gloactiongroup.h      |   36 +
 vcl/inc/unx/gtk/glomenu.h             |  156 +++-----
 vcl/inc/unx/gtk/gtksalmenu.hxx        |   67 +--
 vcl/unx/gtk/app/gtkinst.cxx           |    2 
 vcl/unx/gtk/window/gloactiongroup.cxx |  249 ++++++++++---
 vcl/unx/gtk/window/glomenu.cxx        |  646 +++++++++++++---------------------
 vcl/unx/gtk/window/gtksalmenu.cxx     |  579 ++++++++++++++++++------------
 7 files changed, 957 insertions(+), 778 deletions(-)

New commits:
commit 5a5e985e2c01b69bb0add4b5911870142a6b9ad3
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Sat Aug 25 22:44:09 2012 +0100

    GLOMenu class is now mostly implemented, but menus are buggy at the moment.
    
    Change-Id: Ib7c657efdd167f66e94717dda71d722196ae1667

diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h
index 852a40f..4392e18 100644
--- a/vcl/inc/unx/gtk/gloactiongroup.h
+++ b/vcl/inc/unx/gtk/gloactiongroup.h
@@ -1,3 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * Copyright © 2011 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
+ */
+
 #ifndef GLOACTIONGROUP_H
 #define GLOACTIONGROUP_H
 
@@ -46,10 +69,21 @@ void                g_lo_action_group_insert                (GLOActionGroup *gro
                                                              const gchar    *action_name,
                                                              gpointer        action_info);
 
+void                g_lo_action_group_insert_stateful       (GLOActionGroup     *group,
+                                                             const gchar        *action_name,
+                                                             gpointer            action_info,
+                                                             const GVariantType *parameter_type,
+                                                             const GVariantType *state_type,
+                                                             GVariant           *state_hint,
+                                                             GVariant           *state);
+
 void                g_lo_action_group_set_action_enabled    (GLOActionGroup *group,
                                                              const gchar    *action_name,
                                                              gboolean        enabled);
 
+gpointer            g_lo_action_group_get_action_item       (GLOActionGroup *group,
+                                                             const gchar    *action_name);
+
 void                g_lo_action_group_remove                (GLOActionGroup *group,
                                                              const gchar    *action_name);
 
@@ -61,3 +95,5 @@ void                g_lo_action_group_merge                 (GLOActionGroup *inp
 G_END_DECLS
 
 #endif // GLOACTIONGROUP_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/glomenu.h b/vcl/inc/unx/gtk/glomenu.h
index db2f034..ab43897 100644
--- a/vcl/inc/unx/gtk/glomenu.h
+++ b/vcl/inc/unx/gtk/glomenu.h
@@ -1,3 +1,5 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
 /*
  * Copyright © 2011 Canonical Ltd.
  *
@@ -16,7 +18,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  * USA.
  *
- * Author: Ryan Lortie <desrt at desrt.ca>
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
  */
 
 #ifndef __G_LO_MENU_H__
@@ -24,6 +26,8 @@
 
 #include <gio/gio.h>
 
+#define G_LO_MENU_ATTRIBUTE_ACCELERATOR     "accel"
+
 G_BEGIN_DECLS
 
 #define G_TYPE_LO_MENU          (g_lo_menu_get_type ())
@@ -32,103 +36,89 @@ G_BEGIN_DECLS
 #define G_IS_LO_MENU(inst)      (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
                                  G_TYPE_LO_MENU))
 
-#define G_TYPE_LO_MENU_ITEM     (g_lo_menu_item_get_type ())
-#define G_LO_MENU_ITEM(inst)    (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
-                                 G_TYPE_LO_MENU_ITEM, GLOMenuItem))
-#define G_IS_LO_MENU_ITEM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
-                                 G_TYPE_LO_MENU_ITEM))
-
-typedef struct _GLOMenuItem GLOMenuItem;
 typedef struct _GLOMenu     GLOMenu;
 
+class GtkSalMenuItem;
+
 GLIB_AVAILABLE_IN_2_32
 GType           g_lo_menu_get_type                          (void) G_GNUC_CONST;
 GLIB_AVAILABLE_IN_2_32
 GLOMenu *       g_lo_menu_new                               (void);
 
-void            g_lo_menu_freeze                            (GLOMenu     *menu);
+void            g_lo_menu_insert                      (GLOMenu        *menu,
+                                                            gint            position,
+                                                            const char     *label);
 
-void            g_lo_menu_insert_item                       (GLOMenu     *menu,
-                                                             gint         position,
-                                                             GLOMenuItem *item);
-void            g_lo_menu_prepend_item                      (GLOMenu     *menu,
-                                                             GLOMenuItem *item);
-void            g_lo_menu_append_item                       (GLOMenu     *menu,
-                                                             GLOMenuItem *item);
-void            g_lo_menu_remove                            (GLOMenu     *menu,
-                                                             gint         position);
-
-void            g_lo_menu_insert                            (GLOMenu     *menu,
-                                                             gint         position,
-                                                             const gchar *label,
-                                                             const gchar *detailed_action);
-void            g_lo_menu_prepend                           (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             const gchar *detailed_action);
-void            g_lo_menu_append                            (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             const gchar *detailed_action);
+void            g_lo_menu_insert_in_section           (GLOMenu        *menu,
+                                                       gint            section,
+                                                       gint            position,
+                                                       const gchar    *label);
 
 void            g_lo_menu_insert_section                    (GLOMenu     *menu,
                                                              gint         position,
-                                                             const gchar *label,
-                                                             GMenuModel  *section);
-void            g_lo_menu_prepend_section                   (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             GMenuModel  *section);
-void            g_lo_menu_append_section                    (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             GMenuModel  *section);
-
-void            g_lo_menu_insert_submenu                    (GLOMenu     *menu,
+                                                             const gchar *label);
+
+void            g_lo_menu_remove                            (GLOMenu        *menu,
+                                                             gint            position);
+
+void            g_lo_menu_remove_from_section               (GLOMenu        *menu,
+                                                             gint            section,
+                                                             gint            position);
+
+//void            g_lo_menu_insert                            (GLOMenu     *menu,
+//                                                             gint         position,
+//                                                             const gchar *label);
+
+//void            g_lo_menu_append                            (GLOMenu     *menu,
+//                                                             const gchar *label,
+//                                                             const gchar *detailed_action);
+
+//void            g_lo_menu_insert_submenu                    (GLOMenu     *menu,
+//                                                             gint         position,
+//                                                             const gchar *label,
+//                                                             GMenuModel  *submenu);
+//void            g_lo_menu_prepend_submenu                   (GLOMenu     *menu,
+//                                                             const gchar *label,
+//                                                             GMenuModel  *submenu);
+//void            g_lo_menu_append_submenu                    (GLOMenu     *menu,
+//                                                             const gchar *label,
+//                                                             GMenuModel  *submenu);
+
+void            g_lo_menu_set_label                         (GLOMenu     *menu,
+                                                             gint         position,
+                                                             const gchar *label);
+
+void            g_lo_menu_set_label_in_section              (GLOMenu     *menu,
+                                                             gint         section,
                                                              gint         position,
-                                                             const gchar *label,
-                                                             GMenuModel  *submenu);
-void            g_lo_menu_prepend_submenu                   (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             GMenuModel  *submenu);
-void            g_lo_menu_append_submenu                    (GLOMenu     *menu,
-                                                             const gchar *label,
-                                                             GMenuModel  *submenu);
-
-
-GType           g_lo_menu_item_get_type                     (void) G_GNUC_CONST;
-GLOMenuItem *   g_lo_menu_item_new                          (const gchar *label,
-                                                             const gchar *detailed_action);
-
-GLOMenuItem *   g_lo_menu_item_new_submenu                  (const gchar *label,
-                                                             GMenuModel  *submenu);
-
-GLOMenuItem *   g_lo_menu_item_new_section                  (const gchar *label,
-                                                             GMenuModel  *section);
-
-void            g_lo_menu_item_set_attribute_value          (GLOMenuItem *menu_item,
-                                                             const gchar *attribute,
-                                                             GVariant    *value);
-void            g_lo_menu_item_set_attribute                (GLOMenuItem *menu_item,
-                                                             const gchar *attribute,
-                                                             const gchar *format_string,
-                                                             ...);
-void            g_lo_menu_item_set_link                     (GLOMenuItem *menu_item,
-                                                             const gchar *link,
-                                                             GMenuModel  *model);
-void            g_lo_menu_item_set_label                    (GLOMenuItem *menu_item,
                                                              const gchar *label);
-void            g_lo_menu_item_set_submenu                  (GLOMenuItem *menu_item,
-                                                             GMenuModel  *submenu);
-void            g_lo_menu_item_set_section                  (GLOMenuItem *menu_item,
-                                                             GMenuModel  *section);
-void            g_lo_menu_item_set_action_and_target_value  (GLOMenuItem *menu_item,
-                                                             const gchar *action,
-                                                             GVariant    *target_value);
-void            g_lo_menu_item_set_action_and_target        (GLOMenuItem *menu_item,
-                                                             const gchar *action,
-                                                             const gchar *format_string,
-                                                             ...);
-void            g_lo_menu_item_set_detailed_action          (GLOMenuItem *menu_item,
-                                                             const gchar *detailed_action);
+
+void g_lo_menu_set_action_and_target_value (GLOMenu     *menu,
+                                            gint         position,
+                                            const gchar *command,
+                                            GVariant    *target_value);
+
+void g_lo_menu_set_action_and_target_value_to_item_in_section (GLOMenu     *menu,
+                                                               gint section,
+                                            gint         position,
+                                            const gchar *command,
+                                            GVariant    *target_value);
+
+void            g_lo_menu_set_submenu                  (GLOMenu    *menu,
+                                                        gint        position,
+                                                        GMenuModel *submenu);
+
+void            g_lo_menu_set_submenu_to_item_in_section    (GLOMenu    *menu,
+                                                             gint        section,
+                                                             gint        position,
+                                                             GMenuModel *submenu);
+
+gchar* g_lo_menu_get_action_value_from_item_in_section (GLOMenu *menu,
+                                                 gint section,
+                                                 gint position);
 
 G_END_DECLS
 
 #endif /* __G_LO_MENU_H__ */
 
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 9332cb6..a517c5e 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -1,30 +1,25 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
+
+/*
+ * Copyright © 2011 Canonical Ltd.
  *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
  *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org.  If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
  *
- ************************************************************************/
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
+ */
 
 #ifndef GTKSALMENU_HXX
 #define GTKSALMENU_HXX
@@ -39,32 +34,25 @@
 #include "glomenu.h"
 #include "gloactiongroup.h"
 
-#include <vector>
-
 
+class MenuItemList;
 class GtkSalMenuItem;
 
 class GtkSalMenu : public SalMenu
 {
 private:
+    std::vector< GtkSalMenuItem* >  maItems;
+
     sal_Bool                        mbMenuBar;
     Menu*                           mpVCLMenu;
     GtkSalMenu*                     mpParentSalMenu;
     const GtkSalFrame*              mpFrame;
 
-    std::vector< GMenuModel* >      maSections;
-    std::vector< GtkSalMenuItem* >  maItems;
-
-    // DBus attributes
-    GDBusConnection*                pSessionBus;
-    sal_Int32                       mMenubarId;
-    sal_Int32                       mActionGroupId;
-
     // GMenuModel and GActionGroup attributes
     GMenuModel*                     mpMenuModel;
     GActionGroup*                   mpActionGroup;
 
-    GtkSalMenuItem* GetSalMenuItem( sal_uInt16 nId );
+
     sal_Int16       GetSectionNumber( GMenuModel* pSection );
     void            GetInsertionData( unsigned nPos, unsigned *insertSection, unsigned *insertPos );
 
@@ -93,10 +81,10 @@ public:
     virtual Menu*               GetMenu() { return mpVCLMenu; }
     virtual GtkSalMenu*         GetParentSalMenu() { return mpParentSalMenu; }
     virtual GMenuModel*         GetMenuModel() { return mpMenuModel; }
-//    virtual GMenuModel*         GetCurrentSection() { return mpCurrentSection; }
     virtual unsigned            GetItemCount() { return maItems.size(); }
     virtual GtkSalMenuItem*     GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
     virtual GActionGroup*       GetActionGroup() { return mpActionGroup; }
+//    virtual GtkSalMenuItem*     GetSalMenuItem( sal_uInt16 nId );
 };
 
 class GtkSalMenuItem : public SalMenuItem
@@ -107,14 +95,10 @@ public:
 
     sal_uInt16          mnId;               // Item ID
     MenuItemBits        mnBits;             // Item bits
-    gchar*              maCommand;          // Item command
+    MenuItemType        mnType;             // Item type
     Menu*               mpVCLMenu;          // VCL Menu into which this MenuItem is inserted
     GtkSalMenu*         mpParentMenu;       // The menu in which this menu item is inserted
     GtkSalMenu*         mpSubMenu;          // Sub menu of this item (if defined)
-    GMenuModel*         mpParentSection;    // Section where this item is added.
-    GLOMenuItem*        mpMenuItem;         // The GMenuItem
-    GVariantType*       mpStateType;        // A GVariantType with item state type
-    GVariant*           mpState;            // A GVariant with current item state
 };
 
 #endif // GTKSALMENU_HXX
diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx
index 2e00b34..6c9e198 100644
--- a/vcl/unx/gtk/app/gtkinst.cxx
+++ b/vcl/unx/gtk/app/gtkinst.cxx
@@ -543,7 +543,7 @@ SalMenuItem* GtkInstance::CreateMenuItem( const SalItemParams* pItemData )
 void GtkInstance::DestroyMenuItem( SalMenuItem* pItem )
 {
     (void)pItem;
-//    delete pItem;
+    delete pItem;
 //    OSL_ENSURE( pItem == 0, "DestroyMenu called with non-native menus" );
 }
 
diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
index a409015..39ab45e 100644
--- a/vcl/unx/gtk/window/gloactiongroup.cxx
+++ b/vcl/unx/gtk/window/gloactiongroup.cxx
@@ -1,3 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * Copyright © 2011 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
+ */
+
 #include <unx/gtk/gloactiongroup.h>
 
 #include <unx/gtk/gtkinst.hxx>
@@ -10,6 +33,92 @@
 
 using namespace std;
 
+/*
+ * GLOAction
+ */
+
+#define G_TYPE_LO_ACTION                                (g_lo_action_get_type ())
+#define G_LO_ACTION(inst)                               (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                             G_TYPE_LO_ACTION, GLOAction))
+#define G_IS_LO_ACTION(inst)                            (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                             G_TYPE_LO_ACTION))
+
+struct _GLOAction
+{
+    GObject         parent_instance;
+
+    GtkSalMenuItem* item;               // A pointer to the menu item.
+    gboolean        enabled;            // TRUE if action is enabled, FALSE otherwise.
+    GVariantType*   parameter_type;     // A GVariantType with the action parameter type.
+    GVariantType*   state_type;         // A GVariantType with item state type
+    GVariant*       state_hint;         // A GVariant with state hints.
+    GVariant*       state;              // A GVariant with current item state
+};
+
+typedef GObjectClass GLOActionClass;
+typedef struct _GLOAction GLOAction;
+
+G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT);
+
+GLOAction*
+g_lo_action_new (void)
+{
+    return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION, NULL));
+}
+
+static void
+g_lo_action_init (GLOAction *action)
+{
+    action->item = NULL;
+    action->enabled = FALSE;
+    action->parameter_type = NULL;
+    action->state_type = NULL;
+    action->state_hint = NULL;
+    action->state = NULL;
+}
+
+static void
+g_lo_action_finalize (GObject *object)
+{
+    GLOAction* action = G_LO_ACTION(object);
+
+    action->item = NULL;
+
+    if (action->parameter_type) {
+        g_variant_type_free (action->parameter_type);
+        action->parameter_type = NULL;
+    }
+
+    if (action->state_type) {
+        g_variant_type_free (action->state_type);
+        action->state_type = NULL;
+    }
+
+    if (action->state_hint) {
+        g_variant_unref (action->state_hint);
+        action->state_hint = NULL;
+    }
+
+    if (action->state) {
+        g_variant_unref (action->state);
+        action->state = NULL;
+    }
+
+    G_OBJECT_CLASS (g_lo_action_parent_class)->finalize (object);
+}
+
+static void
+g_lo_action_class_init (GLOActionClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->finalize = g_lo_action_finalize;
+}
+
+/*
+ * GLOActionGroup
+ */
+
 struct _GLOActionGroupPrivate
 {
     GHashTable *table;  /* string -> GtkSalMenuItem* */
@@ -52,35 +161,32 @@ g_lo_action_group_query_action (GActionGroup        *group,
                                 GVariant           **state_hint,
                                 GVariant           **state)
 {
-    GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
-    GtkSalMenuItem* item_info;
+//    cout << __FUNCTION__ << " - " << action_name << " - enabled: " << enabled << " - parameter_type: " << parameter_type << " - state_type: " << state_type << " - state_hint: " << state_hint << " - state: " << state << endl;
+    GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
+    GLOAction* action;
 
-    item_info = static_cast< GtkSalMenuItem* >( g_hash_table_lookup (loGroup->priv->table, action_name) );
+    action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
 
-    if (item_info == NULL)
+    if (action == NULL)
         return FALSE;
 
-    if (enabled) {
-        sal_Bool bEnabled = item_info->mpVCLMenu->IsItemEnabled( item_info->mnId );
-        *enabled = (bEnabled) ? TRUE : FALSE;
-    }
+    if (enabled)
+        *enabled = action->enabled;
 
-    if (parameter_type)
-        *parameter_type = NULL;
+    if (parameter_type) {
+        *parameter_type = action->parameter_type;
+    }
 
-    if (state_type)
-        *state_type = item_info->mpStateType;
+    if (state_type) {
+        *state_type = action->state_type;
+    }
 
-    if (state_hint)
-        *state_hint = NULL;
+    if (state_hint) {
+        *state_hint = (action->state_hint) ? g_variant_ref(action->state_hint) : NULL;
+    }
 
     if (state) {
-        if (item_info->mpState) {
-            g_variant_ref( item_info->mpState );
-            *state = item_info->mpState;
-        } else {
-            *state = NULL;
-        }
+        *state = (action->state) ? g_variant_ref(action->state) : NULL;
     }
 
     return TRUE;
@@ -95,24 +201,23 @@ g_lo_action_group_change_state (GActionGroup *group,
         return;
 
     GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
-    GtkSalMenuItem* item_info;
 
-    item_info = static_cast<GtkSalMenuItem*>( g_hash_table_lookup (lo_group->priv->table, action_name) );
+    GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
 
-    if (!item_info)
+    if (action == NULL)
         return;
 
-    if (!item_info->mpStateType) {
-        item_info->mpStateType = g_variant_type_copy(g_variant_get_type(value));
-    }
+    if (action->state_type == NULL)
+        action->state_type = g_variant_type_copy(g_variant_get_type(value));
 
-    if (g_variant_is_of_type(value, item_info->mpStateType)) {
-        if (item_info->mpState)
-            g_variant_unref(item_info->mpState);
+    g_return_if_fail (g_variant_is_of_type(value, action->state_type) == TRUE);
 
-        item_info->mpState = g_variant_new_variant(value);
-        g_action_group_action_state_changed(group, action_name, value);
-    }
+    if (action->state)
+        g_variant_unref(action->state);
+
+    action->state = g_variant_take_ref(value);
+
+    g_action_group_action_state_changed(group, action_name, value);
 }
 
 static void
@@ -120,16 +225,15 @@ g_lo_action_group_activate (GActionGroup *group,
                             const gchar  *action_name,
                             GVariant     *parameter)
 {
-    GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
-    GtkSalMenuItem *pSalMenuItem;
+    GTK_YIELD_GRAB();
 
-    pSalMenuItem = static_cast< GtkSalMenuItem* >( g_hash_table_lookup (loGroup->priv->table, action_name) );
+    GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
+    GLOAction* action = G_LO_ACTION (g_hash_table_lookup (loGroup->priv->table, action_name));
+    GtkSalMenuItem *pSalMenuItem = action->item;
 
     if (pSalMenuItem == NULL || pSalMenuItem->mpSubMenu )
         return;
 
-    GTK_YIELD_GRAB();
-
     const GtkSalFrame *pFrame = pSalMenuItem->mpParentMenu ? pSalMenuItem->mpParentMenu->GetFrame() : NULL;
 
     if ( pFrame && !pFrame->GetParent() ) {
@@ -177,18 +281,44 @@ g_lo_action_group_insert (GLOActionGroup *group,
                           const gchar    *action_name,
                           gpointer        action_info)
 {
-    g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+    g_lo_action_group_insert_stateful (group, action_name, action_info, NULL, NULL, NULL, NULL);
+}
 
-    gpointer old_action;
+void
+g_lo_action_group_insert_stateful (GLOActionGroup     *group,
+                                   const gchar        *action_name,
+                                   gpointer            action_info,
+                                   const GVariantType *parameter_type,
+                                   const GVariantType *state_type,
+                                   GVariant           *state_hint,
+                                   GVariant           *state)
+{
+    g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
 
-    old_action = g_hash_table_lookup (group->priv->table, action_name);
+    GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
 
-    if (old_action != action_info)
+    if (old_action == NULL || old_action->item != action_info)
     {
         if (old_action != NULL)
             g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
 
-        g_hash_table_insert (group->priv->table, g_strdup (action_name), action_info);
+        GLOAction* action = g_lo_action_new();
+
+        g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
+
+        action->item = static_cast< GtkSalMenuItem* >( action_info );
+
+        if (parameter_type)
+            action->parameter_type = (GVariantType*) parameter_type;
+
+        if (state_type)
+            action->state_type = (GVariantType*) state_type;
+
+        if (state_hint)
+            action->state_hint = g_variant_take_ref (state_hint);
+
+        if (state)
+            action->state = g_variant_take_ref (state);
 
         g_action_group_action_added (G_ACTION_GROUP (group), action_name);
     }
@@ -197,9 +327,9 @@ g_lo_action_group_insert (GLOActionGroup *group,
 static void
 g_lo_action_group_finalize (GObject *object)
 {
-    GLOActionGroup *loGroup = G_LO_ACTION_GROUP (object);
+    GLOActionGroup *lo_group = G_LO_ACTION_GROUP (object);
 
-    g_hash_table_unref (loGroup->priv->table);
+    g_hash_table_unref (lo_group->priv->table);
 
     G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
 }
@@ -211,7 +341,7 @@ g_lo_action_group_init (GLOActionGroup *group)
                                                  G_TYPE_LO_ACTION_GROUP,
                                                  GLOActionGroupPrivate);
     group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                                  g_free, NULL );
+                                                  g_free, g_object_unref);
 }
 
 static void
@@ -245,11 +375,30 @@ g_lo_action_group_set_action_enabled (GLOActionGroup *group,
                                       gboolean        enabled)
 {
     g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+    g_return_if_fail (action_name != NULL);
+
+    GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
+
+    if (action == NULL)
+        return;
+
+    action->enabled = enabled;
 
     g_action_group_action_enabled_changed(G_ACTION_GROUP(group),
                                           action_name,
                                           enabled);
+}
+
+gpointer
+g_lo_action_group_get_action_item (GLOActionGroup *group,
+                                   const gchar    *action_name)
+{
+    g_return_val_if_fail (G_IS_LO_ACTION_GROUP (group), NULL);
+    g_return_val_if_fail (action_name != NULL, NULL);
+
+    GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
 
+    return (action != NULL) ? action->item : NULL;
 }
 
 void
@@ -270,7 +419,12 @@ g_lo_action_group_clear (GLOActionGroup  *group)
 {
     g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
 
-    g_hash_table_remove_all(group->priv->table);
+    GList* keys = g_hash_table_get_keys (group->priv->table);
+
+    for (GList* element = g_list_first (keys); element != NULL; element = g_list_next (element))
+    {
+        g_lo_action_group_remove (group, (gchar*) element->data);
+    }
 }
 
 void
@@ -292,3 +446,5 @@ g_lo_action_group_merge (GLOActionGroup *input_group,
         g_lo_action_group_insert(output_group, (gchar*) key, value);
     }
 }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/window/glomenu.cxx b/vcl/unx/gtk/window/glomenu.cxx
index 7ada474..989a3b3 100644
--- a/vcl/unx/gtk/window/glomenu.cxx
+++ b/vcl/unx/gtk/window/glomenu.cxx
@@ -1,3 +1,5 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
 /*
  * Copyright © 2011 Canonical Ltd.
  *
@@ -16,51 +18,86 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  * USA.
  *
- * Author: Ryan Lortie <desrt at desrt.ca>
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
  */
 
 #include <stdio.h>
 #include <string.h>
 
-#include <unx/gtk/glomenu.h>
-
-
-struct _GLOMenuItem
-{
-    GObject parent_instance;
-
-    GHashTable *attributes;
-    GHashTable *links;
-    gboolean    cow;
-};
+#include <unx/gtk/gtksalmenu.hxx>
 
-typedef GObjectClass GLOMenuItemClass;
+#include <unx/gtk/glomenu.h>
 
 struct _GLOMenu
 {
-    GMenuModel parent_instance;
+    GMenuModel  parent_instance;
 
-    GArray   *items;
-//    gboolean  mutable;
+    GArray      *items;
 };
 
 typedef GMenuModelClass GLOMenuClass;
 
-G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL)
-G_DEFINE_TYPE (GLOMenuItem, g_lo_menu_item, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL);
 
 struct item
 {
-    GHashTable *attributes;
-    GHashTable *links;
+//    GtkSalMenuItem* menu_item;      // Menu item pointer.
+    GHashTable*     attributes;     // Item attributes.
+    GHashTable*     links;          // Item links.
 };
 
+
+static void
+g_lo_menu_struct_item_init (struct item *menu_item)
+{
+//    menu_item->menu_item = NULL;
+    menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
+    menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
+
+/* We treat attribute names the same as GSettings keys:
+ * - only lowercase ascii, digits and '-'
+ * - must start with lowercase
+ * - must not end with '-'
+ * - no consecutive '-'
+ * - not longer than 1024 chars
+ */
 static gboolean
-g_lo_menu_is_mutable (GMenuModel *model)
+valid_attribute_name (const gchar *name)
 {
-//    GMenu *menu = G_MENU (model);
+    gint i;
+
+    if (!g_ascii_islower (name[0]))
+        return FALSE;
+
+    for (i = 1; name[i]; i++)
+    {
+        if (name[i] != '-' &&
+                !g_ascii_islower (name[i]) &&
+                !g_ascii_isdigit (name[i]))
+            return FALSE;
 
-//    return menu->mutable;
+        if (name[i] == '-' && name[i + 1] == '-')
+            return FALSE;
+    }
+
+    if (name[i - 1] == '-')
+        return FALSE;
+
+    if (i > 1024)
+        return FALSE;
+
+    return TRUE;
+}
+
+/*
+ * GLOMenu
+ */
+
+static gboolean
+g_lo_menu_is_mutable (GMenuModel *model)
+{
+    // Menu is always mutable.
     return TRUE;
 }
 
@@ -74,8 +111,8 @@ g_lo_menu_get_n_items (GMenuModel *model)
 
 static void
 g_lo_menu_get_item_attributes (GMenuModel  *model,
-                            gint         position,
-                            GHashTable **table)
+                               gint         position,
+                               GHashTable **table)
 {
     GLOMenu *menu = G_LO_MENU (model);
 
@@ -84,8 +121,8 @@ g_lo_menu_get_item_attributes (GMenuModel  *model,
 
 static void
 g_lo_menu_get_item_links (GMenuModel  *model,
-                       gint         position,
-                       GHashTable **table)
+                          gint         position,
+                          GHashTable **table)
 {
     GLOMenu *menu = G_LO_MENU (model);
 
@@ -93,46 +130,42 @@ g_lo_menu_get_item_links (GMenuModel  *model,
 }
 
 void
-g_lo_menu_insert_item (GLOMenu     *menu,
-                    gint       position,
-                    GLOMenuItem *item)
+g_lo_menu_insert (GLOMenu        *menu,
+                  gint            position,
+                  const gchar    *label)
 {
-    struct item new_item;
-
+//    puts(__FUNCTION__);
     g_return_if_fail (G_IS_LO_MENU (menu));
-    g_return_if_fail (G_IS_LO_MENU_ITEM (item));
 
     if (position < 0 || position > (gint) menu->items->len)
         position = menu->items->len;
 
-    new_item.attributes = g_hash_table_ref (item->attributes);
-    new_item.links = g_hash_table_ref (item->links);
-    item->cow = TRUE;
+    struct item menu_item;
 
-    g_array_insert_val (menu->items, position, new_item);
-    g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
-}
+    g_lo_menu_struct_item_init(&menu_item);
 
-void
-g_lo_menu_prepend_item (GLOMenu     *menu,
-                     GLOMenuItem *item)
-{
-    g_lo_menu_insert_item (menu, 0, item);
-}
+    g_array_insert_val (menu->items, position, menu_item);
 
-void
-g_lo_menu_append_item (GLOMenu     *menu,
-                    GLOMenuItem *item)
-{
-    g_lo_menu_insert_item (menu, -1, item);
+    g_lo_menu_set_label (menu, position, label);
+
+    g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
 }
 
 void
-g_lo_menu_freeze (GLOMenu *menu)
+g_lo_menu_insert_in_section (GLOMenu        *menu,
+                             gint            section,
+                             gint            position,
+                             const gchar    *label)
 {
     g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (0 <= section && section < (gint) menu->items->len);
 
-//    menu->mutable = FALSE;
+    GLOMenu *model = G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+                                ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION));
+
+    g_return_if_fail (model != NULL);
+
+    g_lo_menu_insert (model, position, label);
 }
 
 GLOMenu *
@@ -142,436 +175,279 @@ g_lo_menu_new (void)
 }
 
 void
-g_lo_menu_insert (GLOMenu     *menu,
-                  gint         position,
-                  const gchar *label,
-                  const gchar *detailed_action)
+g_lo_menu_set_attribute_value (GLOMenu     *menu,
+                               gint         position,
+                               const gchar *attribute,
+                               GVariant    *value)
 {
-    GLOMenuItem *menu_item;
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (attribute != NULL);
+    g_return_if_fail (valid_attribute_name (attribute));
 
-    menu_item = g_lo_menu_item_new (label, detailed_action);
-    g_lo_menu_insert_item (menu, position, menu_item);
-    g_object_unref (menu_item);
-}
+    if (position >= menu->items->len)
+        return;
 
-void
-g_lo_menu_prepend (GLOMenu     *menu,
-                   const gchar *label,
-                   const gchar *detailed_action)
-{
-    g_lo_menu_insert (menu, 0, label, detailed_action);
-}
+    struct item menu_item = g_array_index (menu->items, struct item, position);
 
-void
-g_lo_menu_append (GLOMenu     *menu,
-                  const gchar *label,
-                  const gchar *detailed_action)
-{
-    g_lo_menu_insert (menu, -1, label, detailed_action);
+    if (value != NULL)
+        g_hash_table_insert (menu_item.attributes, g_strdup (attribute), g_variant_ref_sink (value));
+    else
+        g_hash_table_remove (menu_item.attributes, attribute);
 }
 
 void
-g_lo_menu_insert_section (GLOMenu     *menu,
-                          gint         position,
-                          const gchar *label,
-                          GMenuModel  *section)
+g_lo_menu_set_label (GLOMenu     *menu,
+                     gint         position,
+                     const gchar *label)
 {
-    GLOMenuItem *menu_item;
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
 
-    menu_item = g_lo_menu_item_new_section (label, section);
-    g_lo_menu_insert_item (menu, position, menu_item);
-    g_object_unref (menu_item);
-}
+    GVariant *value;
 
-void
-g_lo_menu_prepend_section (GLOMenu     *menu,
-                           const gchar *label,
-                           GMenuModel  *section)
-{
-    g_lo_menu_insert_section (menu, 0, label, section);
-}
+    if (label != NULL)
+        value = g_variant_new_string (label);
+    else
+        value = NULL;
 
-void
-g_lo_menu_append_section (GLOMenu     *menu,
-                          const gchar *label,
-                          GMenuModel  *section)
-{
-    g_lo_menu_insert_section (menu, -1, label, section);
+    g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_LABEL, value);
 }
 
 void
-g_lo_menu_insert_submenu (GLOMenu     *menu,
-                          gint         position,
-                          const gchar *label,
-                          GMenuModel  *submenu)
+g_lo_menu_set_label_in_section (GLOMenu     *menu,
+                                gint         section,
+                                gint         position,
+                                const gchar *label)
 {
-    GLOMenuItem *menu_item;
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
 
-    menu_item = g_lo_menu_item_new_submenu (label, submenu);
-    g_lo_menu_insert_item (menu, position, menu_item);
-    g_object_unref (menu_item);
-}
+    struct item menu_item = g_array_index (menu->items, struct item, section);
 
-void
-g_lo_menu_prepend_submenu (GLOMenu     *menu,
-                           const gchar *label,
-                           GMenuModel  *submenu)
-{
-    g_lo_menu_insert_submenu (menu, 0, label, submenu);
-}
+    GLOMenu *model = G_LO_MENU (g_hash_table_lookup (menu_item.links, G_MENU_LINK_SECTION));
 
-void
-g_lo_menu_append_submenu (GLOMenu     *menu,
-                          const gchar *label,
-                          GMenuModel  *submenu)
-{
-    g_lo_menu_insert_submenu (menu, -1, label, submenu);
-}
+    g_return_if_fail (model != NULL);
 
-static void
-g_lo_menu_clear_item (struct item *item)
-{
-    if (item->attributes != NULL)
-        g_hash_table_unref (item->attributes);
-    if (item->links != NULL)
-        g_hash_table_unref (item->links);
+    g_lo_menu_set_label (model, position, label);
 }
 
 void
-g_lo_menu_remove (GLOMenu *menu,
-                  gint     position)
+g_lo_menu_set_action_and_target_value (GLOMenu     *menu,
+                                       gint         position,
+                                       const gchar *action,
+                                       GVariant    *target_value)
 {
+//    puts(__FUNCTION__);
     g_return_if_fail (G_IS_LO_MENU (menu));
-    g_return_if_fail (0 <= position && position < (gint) menu->items->len);
-
-    g_lo_menu_clear_item (&g_array_index (menu->items, struct item, position));
-    g_array_remove_index (menu->items, position);
-    g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
-}
-
-static void
-g_lo_menu_finalize (GObject *object)
-{
-    GLOMenu *menu = G_LO_MENU (object);
-    struct item *items;
-    gint n_items;
-    gint i;
-
-    n_items = menu->items->len;
-    items = (struct item *) g_array_free (menu->items, FALSE);
-    for (i = 0; i < n_items; i++)
-        g_lo_menu_clear_item (&items[i]);
-    g_free (items);
-
-    G_OBJECT_CLASS (g_lo_menu_parent_class)
-            ->finalize (object);
-}
-
-static void
-g_lo_menu_init (GLOMenu *menu)
-{
-    menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
-//    menu->mutable = TRUE;
-}
-
-static void
-g_lo_menu_class_init (GLOMenuClass *klass)
-{
-    GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass);
-    GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-    object_class->finalize = g_lo_menu_finalize;
-
-    model_class->is_mutable = g_lo_menu_is_mutable;
-    model_class->get_n_items = g_lo_menu_get_n_items;
-    model_class->get_item_attributes = g_lo_menu_get_item_attributes;
-    model_class->get_item_links = g_lo_menu_get_item_links;
-}
 
+    GVariant *action_value;
 
-static void
-g_lo_menu_item_clear_cow (GLOMenuItem *menu_item)
-{
-    if (menu_item->cow)
+    if (action != NULL)
     {
-        GHashTableIter iter;
-        GHashTable *newHash;
-        gpointer key;
-        gpointer val;
-
-        newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
-        g_hash_table_iter_init (&iter, menu_item->attributes);
-        while (g_hash_table_iter_next (&iter, &key, &val))
-            g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_variant_ref ((GVariant*) val));
-        g_hash_table_unref (menu_item->attributes);
-        menu_item->attributes = newHash;
-
-        newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
-        g_hash_table_iter_init (&iter, menu_item->links);
-        while (g_hash_table_iter_next (&iter, &key, &val))
-            g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_object_ref (val));
-        g_hash_table_unref (menu_item->links);
-        menu_item->links = newHash;
-
-        menu_item->cow = FALSE;
+        action_value = g_variant_new_string (action);
     }
+    else
+    {
+        action_value = NULL;
+        target_value = NULL;
+    }
+
+    g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ACTION, action_value);
+    g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_TARGET, target_value);
 }
 
-static void
-g_lo_menu_item_finalize (GObject *object)
+void
+g_lo_menu_set_action_and_target_value_to_item_in_section (GLOMenu     *menu,
+                                                          gint         section,
+                                                          gint         position,
+                                                          const gchar *command,
+                                                          GVariant    *target_value)
 {
-    GLOMenuItem *menu_item = G_LO_MENU_ITEM (object);
+    g_return_if_fail (G_IS_LO_MENU (menu));
 
-    g_hash_table_unref (menu_item->attributes);
-    g_hash_table_unref (menu_item->links);
+    struct item menu_item = g_array_index (menu->items, struct item, section);
 
-    G_OBJECT_CLASS (g_lo_menu_item_parent_class)
-            ->finalize (object);
-}
+    GLOMenu *model = G_LO_MENU (g_hash_table_lookup (menu_item.links, G_MENU_LINK_SECTION));
 
-static void
-g_lo_menu_item_init (GLOMenuItem *menu_item)
-{
-    menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
-    menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-    menu_item->cow = FALSE;
-}
+    g_return_if_fail (model != NULL);
 
-static void
-g_lo_menu_item_class_init (GLOMenuItemClass *klass)
-{
-    klass->finalize = g_lo_menu_item_finalize;
+    g_lo_menu_set_action_and_target_value (model, position, command, target_value);
 }
 
-/* We treat attribute names the same as GSettings keys:
- * - only lowercase ascii, digits and '-'
- * - must start with lowercase
- * - must not end with '-'
- * - no consecutive '-'
- * - not longer than 1024 chars
- */
-static gboolean
-valid_attribute_name (const gchar *name)
+gchar*
+g_lo_menu_get_action_value_from_item_in_section (GLOMenu *menu,
+                                                 gint section,
+                                                 gint position)
 {
-    gint i;
+    g_return_val_if_fail (G_IS_LO_MENU (menu), NULL);
 
-    if (!g_ascii_islower (name[0]))
-        return FALSE;
+    GMenuModel *model = G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+                                ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION);
 
-    for (i = 1; name[i]; i++)
-    {
-        if (name[i] != '-' &&
-                !g_ascii_islower (name[i]) &&
-                !g_ascii_isdigit (name[i]))
-            return FALSE;
+    GVariant *action = g_menu_model_get_item_attribute_value (model, position, G_MENU_ATTRIBUTE_LABEL, NULL);
 
-        if (name[i] == '-' && name[i + 1] == '-')
-            return FALSE;
-    }
+    gchar *action_name = NULL;
 
-    if (name[i - 1] == '-')
-        return FALSE;
+    if (action)
+        action_name = g_strdup (g_variant_get_string (action, NULL));
 
-    if (i > 1024)
-        return FALSE;
-
-    return TRUE;
+    return action_name;
 }
 
 void
-g_lo_menu_item_set_attribute_value (GLOMenuItem *menu_item,
-                                    const gchar *attribute,
-                                    GVariant    *value)
+g_lo_menu_set_link (GLOMenu     *menu,
+                    gint         position,
+                    const gchar *link,
+                    GMenuModel  *model)
 {
-    g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item));
-    g_return_if_fail (attribute != NULL);
-    g_return_if_fail (valid_attribute_name (attribute));
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (link != NULL);
+    g_return_if_fail (valid_attribute_name (link));
 
-    g_lo_menu_item_clear_cow (menu_item);
+    if (position < 0 || position >= (gint) menu->items->len)
+        position = menu->items->len - 1;
 
-    if (value != NULL)
-        g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value));
+    struct item menu_item = g_array_index (menu->items, struct item, position);
+
+    if (model != NULL)
+        g_hash_table_insert (menu_item.links, g_strdup (link), g_object_ref (model));
     else
-        g_hash_table_remove (menu_item->attributes, attribute);
+        g_hash_table_remove (menu_item.links, link);
 }
 
 void
-g_lo_menu_item_set_attribute (GLOMenuItem *menu_item,
-                              const gchar *attribute,
-                              const gchar *format_string,
-                              ...)
+g_lo_menu_insert_section (GLOMenu     *menu,
+                          gint         position,
+                          const gchar *label)
 {
-    GVariant *value;
-
-    if (format_string != NULL)
-    {
-        va_list ap;
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
 
-        va_start (ap, format_string);
-        value = g_variant_new_va (format_string, NULL, &ap);
-        va_end (ap);
-    }
-    else
-        value = NULL;
+    if (position < 0 || position > (gint) menu->items->len)
+        position = menu->items->len;
 
-    g_lo_menu_item_set_attribute_value (menu_item, attribute, value);
-}
+    struct item menu_item;
 
-void
-g_lo_menu_item_set_link (GLOMenuItem *menu_item,
-                         const gchar *link,
-                         GMenuModel  *model)
-{
-    g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item));
-    g_return_if_fail (link != NULL);
-    g_return_if_fail (valid_attribute_name (link));
+    g_lo_menu_struct_item_init(&menu_item);
 
-    g_lo_menu_item_clear_cow (menu_item);
+    g_array_insert_val (menu->items, position, menu_item);
 
-    if (model != NULL)
-        g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model));
-    else
-        g_hash_table_remove (menu_item->links, link);
-}
+    g_lo_menu_set_label (menu, position, label);
 
-void
-g_lo_menu_item_set_label (GLOMenuItem *menu_item,
-                          const gchar *label)
-{
-    GVariant *value;
+    GMenuModel *section = G_MENU_MODEL (g_lo_menu_new());
+    g_lo_menu_set_link (menu, position, G_MENU_LINK_SECTION, section);
 
-    if (label != NULL)
-        value = g_variant_new_string (label);
-    else
-        value = NULL;
+    g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
 
-    g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value);
+//    g_lo_menu_insert (menu, position, label);
+//    menu_item = g_lo_menu_item_new_section (label, section);
+//    g_lo_menu_insert_item (menu, position, menu_item);
+//    g_object_unref (menu_item);
 }
 
 void
-g_lo_menu_item_set_submenu (GLOMenuItem *menu_item,
-                            GMenuModel  *submenu)
+g_lo_menu_set_submenu (GLOMenu    *menu,
+                       gint        position,
+                       GMenuModel *submenu)
 {
-    g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu);
+//    puts(__FUNCTION__);
+    g_lo_menu_set_link (menu, position, G_MENU_LINK_SUBMENU, submenu);
 }
 
 void
-g_lo_menu_item_set_section (GLOMenuItem *menu_item,
-                            GMenuModel  *section)
+g_lo_menu_set_submenu_to_item_in_section (GLOMenu    *menu,
+                                          gint        section,
+                                          gint        position,
+                                          GMenuModel *submenu)
 {
-    g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section);
-}
+//    puts(__FUNCTION__);
+    g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (0 <= section && section < (gint) menu->items->len);
 
-void
-g_lo_menu_item_set_action_and_target_value (GLOMenuItem *menu_item,
-                                            const gchar *action,
-                                            GVariant    *target_value)
-{
-    GVariant *action_value;
+    GLOMenu *model = G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+                                ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION));
 
-    if (action != NULL)
-    {
-        action_value = g_variant_new_string (action);
-    }
-    else
-    {
-        action_value = NULL;
-        target_value = NULL;
-    }
+    g_return_if_fail (model != NULL);
 
-    g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value);
-    g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value);
+    g_lo_menu_set_submenu (model, position, submenu);
 }
 
-void
-g_lo_menu_item_set_action_and_target (GLOMenuItem *menu_item,
-                                      const gchar *action,
-                                      const gchar *format_string,
-                                      ...)
+static void
+g_lo_menu_clear_item (struct item *menu_item)
 {
-    GVariant *value;
-
-    if (format_string != NULL)
-    {
-        va_list ap;
-
-        va_start (ap, format_string);
-        value = g_variant_new_va (format_string, NULL, &ap);
-        va_end (ap);
-    }
-    else
-        value = NULL;
-
-    g_lo_menu_item_set_action_and_target_value (menu_item, action, value);
+    if (menu_item->attributes != NULL)
+        g_hash_table_unref (menu_item->attributes);
+    if (menu_item->links != NULL)
+        g_hash_table_unref (menu_item->links);
 }
 
 void
-g_lo_menu_item_set_detailed_action (GLOMenuItem *menu_item,
-                                    const gchar *detailed_action)
+g_lo_menu_remove (GLOMenu *menu,
+                  gint     position)
 {
-    const gchar *sep;
-
-    sep = strstr (detailed_action, "::");
-
-    if (sep != NULL)
-    {
-        gchar *action;
-
-        action = g_strndup (detailed_action, sep - detailed_action);
-        g_lo_menu_item_set_action_and_target (menu_item, action, "s", sep + 2);
-        g_free (action);
-    }
+    printf("%s - %d\n", __FUNCTION__, position);
+    g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (0 <= position && position < (gint) menu->items->len);
 
-    else
-        g_lo_menu_item_set_action_and_target_value (menu_item, detailed_action, NULL);
+    g_lo_menu_clear_item (&g_array_index (menu->items, struct item, position));
+    g_array_remove_index (menu->items, position);
+    g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
 }
 
-GLOMenuItem *
-g_lo_menu_item_new (const gchar *label,
-                    const gchar *detailed_action)
+void
+g_lo_menu_remove_from_section (GLOMenu *menu,
+                               gint     section,
+                               gint     position)
 {
-    GLOMenuItem *menu_item;
-
-    menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
+    g_return_if_fail (G_IS_LO_MENU (menu));
+    g_return_if_fail (0 <= section && section < (gint) menu->items->len);
 
-    if (label != NULL)
-        g_lo_menu_item_set_label (menu_item, label);
+    GLOMenu *model = G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+                                ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION));
 
-    if (detailed_action != NULL)
-        g_lo_menu_item_set_detailed_action (menu_item, detailed_action);
+    g_return_if_fail (model != NULL);
 
-    return menu_item;
+    g_lo_menu_remove (model, position);
 }
 
-GLOMenuItem *
-g_lo_menu_item_new_submenu (const gchar *label,
-                            GMenuModel  *submenu)
+static void
+g_lo_menu_finalize (GObject *object)
 {
-    GLOMenuItem *menu_item;
-
-    menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
-
-    if (label != NULL)
-        g_lo_menu_item_set_label (menu_item, label);
+    GLOMenu *menu = G_LO_MENU (object);
+    struct item *items;
+    gint n_items;
+    gint i;
 
-    g_lo_menu_item_set_submenu (menu_item, submenu);
+    n_items = menu->items->len;
+    items = (struct item *) g_array_free (menu->items, FALSE);
+    for (i = 0; i < n_items; i++)
+        g_lo_menu_clear_item (&items[i]);
+    g_free (items);
 
-    return menu_item;
+    G_OBJECT_CLASS (g_lo_menu_parent_class)
+            ->finalize (object);
 }
 
-GLOMenuItem *
-g_lo_menu_item_new_section (const gchar *label,
-                            GMenuModel  *section)
+static void
+g_lo_menu_init (GLOMenu *menu)
 {
-    GLOMenuItem *menu_item;
-
-    menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
+    menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
+}
 
-    if (label != NULL)
-        g_lo_menu_item_set_label (menu_item, label);
+static void
+g_lo_menu_class_init (GLOMenuClass *klass)
+{
+    GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass);
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-    g_lo_menu_item_set_section (menu_item, section);
+    object_class->finalize = g_lo_menu_finalize;
 
-    return menu_item;
+    model_class->is_mutable = g_lo_menu_is_mutable;
+    model_class->get_n_items = g_lo_menu_get_n_items;
+    model_class->get_item_attributes = g_lo_menu_get_item_attributes;
+    model_class->get_item_links = g_lo_menu_get_item_links;
 }
 
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index 7e0004a..1eb32c1 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -1,3 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2011 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Antonio Fernández <antonio.fernandez at aentos.es>
+ */
 
 #include "unx/gtk/gtksalmenu.hxx"
 
@@ -12,59 +33,60 @@
 using namespace std;
 
 //Some menus are special, this is the list of them
-gboolean
-isSpecialSubmenu (OUString command)
-{
-    const gchar * specialSubmenus[11] = {".uno:CharFontName",
-                                         ".uno:FontHeight",
-                                         ".uno:ObjectMenue",
-                                         ".uno:InsertPageHeader",
-                                         ".uno:InsertPageFooter",
-                                         ".uno:ChangeControlType",
-                                         ".uno:AvailableToolbars",
-                                         ".uno:ScriptOrganizer",
-                                         ".uno:RecentFileList",
-                                         ".uno:AddDirect",
-                                         ".uno:AutoPilotMenu"};
-
-    for (gint i = 0; i < 11; i++)
-    {
-        if (command.equals (OUString::createFromAscii (specialSubmenus[i])))
-            return TRUE;
-    }
-    return FALSE;
-}
+//gboolean
+//isSpecialSubmenu (OUString command)
+//{
+//    const gchar * specialSubmenus[11] = {".uno:CharFontName",
+//                                         ".uno:FontHeight",
+//                                         ".uno:ObjectMenue",
+//                                         ".uno:InsertPageHeader",
+//                                         ".uno:InsertPageFooter",
+//                                         ".uno:ChangeControlType",
+//                                         ".uno:AvailableToolbars",
+//                                         ".uno:ScriptOrganizer",
+//                                         ".uno:RecentFileList",
+//                                         ".uno:AddDirect",
+//                                         ".uno:AutoPilotMenu"};
+
+//    for (gint i = 0; i < 11; i++)
+//    {
+//        if (command.equals (OUString::createFromAscii (specialSubmenus[i])))
+//            return TRUE;
+//    }
+//    return FALSE;
+//}
 
-void updateNativeMenu( GtkSalMenu* pMenu ) {
+static void UpdateNativeMenu( GtkSalMenu* pMenu ) {
     if ( pMenu == NULL )
         return;
 
-    for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ ) {
-        GtkSalMenuItem* pSalMenuItem = pMenu->GetItemAtPos( i );
+    Menu* pVCLMenu = pMenu->GetMenu();
 
-        Menu* pVCLMenu = pSalMenuItem->mpVCLMenu;
+    for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ ) {
+        sal_uInt16 nId = pVCLMenu->GetItemId( i );
+        GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( i );
 
-        if ( pVCLMenu == NULL )
+        if ( pVCLMenu->GetItemType( nId ) == MENUITEM_SEPARATOR )
             continue;
 
-        sal_uInt16 nId = pSalMenuItem->mnId;
-
         String aText = pVCLMenu->GetItemText( nId );
+        String aCommand = pVCLMenu->GetItemCommand( nId );
         sal_Bool itemEnabled = pVCLMenu->IsItemEnabled( nId );
+        KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
+        sal_Bool itemChecked = pVCLMenu->IsItemChecked( nId );
 
         // Force updating of native menu labels.
         pMenu->SetItemText( i, pSalMenuItem, aText );
-
+        pMenu->SetItemCommand( i, pSalMenuItem, aCommand );
         pMenu->EnableItem( i, itemEnabled );
-
-        //            KeyCode nAccelKey = pSubmenu->GetAccelKey( pSalMenuItem->mnId );
-        //            pMenu->SetAccelerator( i, pSalMenuItem, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+//        pMenu->SetAccelerator( i, pSalMenuItem, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+//        pMenu->CheckItem( i, itemChecked );
 
         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
 
         if ( pSubmenu && pSubmenu->GetMenu() ) {
             pSubmenu->GetMenu()->Activate();
-            updateNativeMenu( pSubmenu );
+            UpdateNativeMenu( pSubmenu );
             pSubmenu->GetMenu()->Deactivate();
         }
     }
@@ -73,7 +95,7 @@ void updateNativeMenu( GtkSalMenu* pMenu ) {
 gboolean GenerateMenu(gpointer user_data) {
     GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( user_data );
 
-    updateNativeMenu( pSalMenu );
+    UpdateNativeMenu( pSalMenu );
 
     return TRUE;
 }
@@ -122,88 +144,100 @@ GActionGroup* GetActionGroupFromMenubar( GtkSalMenu *pMenu )
     return ( pSalMenu ) ? pSalMenu->GetActionGroup() : NULL;
 }
 
-rtl::OUString GetGtkKeyName( rtl::OUString keyName )
-{
-    rtl::OUString aGtkKeyName("");
+//rtl::OUString GetGtkKeyName( rtl::OUString keyName )
+//{
+//    rtl::OUString aGtkKeyName("");
+
+//    sal_Int32 nIndex = 0;
+
+//    do
+//    {
+//        rtl::OUString token = keyName.getToken( 0, '+', nIndex );
+
+//        if ( token == "Ctrl" ) {
+//            aGtkKeyName += "<Control>";
+//        } else if ( token == "Alt" ) {
+//            aGtkKeyName += "<Alt>";
+//        } else if ( token == "Shift" ) {
+//            aGtkKeyName += "<Shift>";
+//        } else {
+//            aGtkKeyName += token;
+//        }
+//    } while ( nIndex >= 0 );
+
+//    return aGtkKeyName;
+//}
+
+//GVariant* GetRadionButtonHints( GtkSalMenuItem *pSalMenuItem )
+//{
+//    GVariantBuilder *pBuilder;
+//    GVariant *pHints;
+
+//    pBuilder = g_variant_builder_new( G_VARIANT_TYPE_STRING );
+
+//    Menu* pMenu = pSalMenuItem->mpVCLMenu;
+
+//    gboolean bItemIncluded = FALSE;
+
+//    for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ )
+//    {
+//        sal_uInt16 nId = pMenu->GetItemId( i );
+//        MenuItemBits itemBits = pMenu->GetItemBits( nId );
+//        MenuItemType itemType = pMenu->GetItemType( nId );
+
+//        if ( itemBits & MIB_RADIOCHECK )
+//        {
+//            rtl::OString aValue = rtl::OUStringToOString( pMenu->GetItemText( nId ), RTL_TEXTENCODING_UTF8 );
+//            g_variant_builder_add( pBuilder, "s", aValue.getStr() );
+
+//            if ( nId == pSalMenuItem->mnId )
+//                bItemIncluded = TRUE;
+//        }
+//        else if ( itemType == MENUITEM_SEPARATOR )
+//        {
+//            if ( bItemIncluded == FALSE )
+//            {
+//                g_variant_builder_clear( pBuilder );
+//            }
+//            else
+//                break;
+//        }
+//    }
 
-    sal_Int32 nIndex = 0;
+//    // Build an array of G_VARIANT_TYPE_STRING.
+//    pHints = g_variant_new ("as", pBuilder);
+//    g_variant_builder_unref ( pBuilder );
 
-    do
-    {
-        rtl::OUString token = keyName.getToken( 0, '+', nIndex );
-
-        if ( token == "Ctrl" ) {
-            aGtkKeyName += "<Control>";
-        } else if ( token == "Alt" ) {
-            aGtkKeyName += "<Alt>";
-        } else if ( token == "Shift" ) {
-            aGtkKeyName += "<Shift>";
-        } else {
-            aGtkKeyName += token;
-        }
-    } while ( nIndex >= 0 );
-
-    return aGtkKeyName;
-}
+//    return pHints;
+//}
 
 /*
  * GtkSalMenu
  */
 
-GtkSalMenuItem* GtkSalMenu::GetSalMenuItem( sal_uInt16 nId )
+void GtkSalMenu::GetInsertionData( unsigned nPos, unsigned *insertSection, unsigned *insertPos )
 {
-    for ( sal_uInt16 i = 0; i < maItems.size(); i++ )
+    if ( mpVCLMenu == NULL || nPos >= mpVCLMenu->GetItemCount() )
     {
-        GtkSalMenuItem* pSalMenuItem = maItems[ i ];
-
-        if ( pSalMenuItem->mnId == nId ) {
-            return pSalMenuItem;
-        }
-
-        if ( pSalMenuItem->mpSubMenu )
-        {
-            pSalMenuItem = pSalMenuItem->mpSubMenu->GetSalMenuItem( nId );
-            if (pSalMenuItem) {
-                return pSalMenuItem;
-            }
-        }
+        *insertSection = g_menu_model_get_n_items( mpMenuModel ) - 1;
+        *insertPos = MENU_APPEND;
     }
-
-    return NULL;
-}
-
-sal_Int16 GtkSalMenu::GetSectionNumber( GMenuModel* pSection )
-{
-    if ( pSection == NULL )
-        return -1;
-
-    for ( int i = 0; maSections.size(); i++ )
+    else
     {
-        if ( maSections[ i ] == pSection )
-            return i;
-    }
-
-    return -1;
-}
+        unsigned nItem;
+        gint nItemPos;
 
-void GtkSalMenu::GetInsertionData( unsigned nPos, unsigned *insertSection, unsigned *insertPos )
-{
-    unsigned nItems;
-    unsigned nSection;
-
-    for ( nSection = 0, nItems = 0; nSection < maSections.size(); nSection++ )
-    {
-        if ( nPos <= nItems + g_menu_model_get_n_items( maSections[ nSection ] ) ) {
-            *insertSection = nSection;
-            *insertPos = nPos - nItems;
-            return;
+        for ( nItem = 0, *insertSection = 0, nItemPos = -1; nItem <= nPos; nItem++ )
+        {
+            if ( mpVCLMenu->GetItemType( nItem ) == MENUITEM_SEPARATOR ) {
+                (*insertSection)++;
+                nItemPos = -1;
+            } else
+                nItemPos++;
         }
 
-        nItems += g_menu_model_get_n_items( maSections[ nSection ] ) + 1;    // +1 to count the separator.
+        *insertPos = nItemPos;
     }
-
-    *insertSection = maSections.size() - 1;
-    *insertPos = MENU_APPEND;
 }
 
 GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
@@ -211,44 +245,32 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mpVCLMenu( NULL ),
     mpParentSalMenu( NULL ),
     mpFrame( NULL ),
-    pSessionBus( NULL ),
-    mMenubarId( 0 ),
-    mActionGroupId ( 0 ),
     mpMenuModel( NULL ),
     mpActionGroup( NULL )
 {
-    GMenuModel* pSection = G_MENU_MODEL( g_lo_menu_new() );
-    maSections.push_back( pSection );
-
     if (bMenuBar) {
         mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new() );
-
-        pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-        if(!pSessionBus) puts ("Fail bus get");
-    } else {
-        mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
-        g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, pSection );
     }
+
+    mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
+    g_lo_menu_insert_section( G_LO_MENU( mpMenuModel ), 0, NULL);
 }
 
 GtkSalMenu::~GtkSalMenu()
 {
-    g_source_remove_by_user_data( this );
+    if ( mpActionGroup ) {
+        g_lo_action_group_clear( G_LO_ACTION_GROUP( mpActionGroup ) );
+    }
 
     if ( mbMenuBar ) {
+        g_source_remove_by_user_data( this );
+
         g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
         mpMenuModel = NULL;
     } else {
         g_object_unref( mpMenuModel );
     }
 
-    if ( mpActionGroup ) {
-        g_lo_action_group_clear( G_LO_ACTION_GROUP( mpActionGroup ) );
-    }
-
-    pSessionBus = NULL;
-
-    maSections.clear();
     maItems.clear();
 }
 
@@ -261,51 +283,56 @@ void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
 {
     GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
 
-    if ( nPos == MENU_APPEND ) {
+    if ( nPos == MENU_APPEND )
         maItems.push_back( pItem );
-    } else {
+    else
         maItems.insert( maItems.begin() + nPos, pItem );
-    }
-
-    if ( pItem->mpMenuItem ) {
-        unsigned nSection, nInsertPos;
 
-        // Get the section number and position to insert the item.
-        GetInsertionData( nPos, &nSection, &nInsertPos );
+    pItem->mpParentMenu = this;
 
-        g_lo_menu_insert_item( G_LO_MENU( maSections[ nSection ] ), nInsertPos, pItem->mpMenuItem );
-    } else {
-        // If no mpMenuItem exists, then item is a separator.
-        GMenuModel* pSection = G_MENU_MODEL( g_lo_menu_new() );
-        maSections.push_back( pSection );
+    if ( pItem->mnType != MENUITEM_SEPARATOR )
+    {
+        unsigned nInsertSection, nInsertPos;
+        GetInsertionData( nPos, &nInsertSection, &nInsertPos );
 
-        if ( mpMenuModel != NULL )
-            g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, pSection );
+        g_lo_menu_insert_in_section( G_LO_MENU( mpMenuModel ), nInsertSection, nInsertPos, "EMPTY STRING" );
+    }
+    else
+    {
+        g_lo_menu_insert_section( G_LO_MENU( mpMenuModel ), MENU_APPEND, NULL );
     }
-
-    pItem->mpParentMenu = this;
 }
 
 void GtkSalMenu::RemoveItem( unsigned nPos )
 {
-    GtkSalMenuItem* pItem = maItems[ nPos ];
-
-    if ( pItem->mpMenuItem != NULL ) {
-        GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
-        if ( pActionGroup ) {
-            g_lo_action_group_remove( pActionGroup, pItem->maCommand );
-        }
+    GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
 
+    // If item is a separator, the last section of the menu is removed.
+    if ( mpVCLMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
+    {
         unsigned nSection, nItemPos;
         GetInsertionData( nPos, &nSection, &nItemPos );
 
-        g_lo_menu_remove( G_LO_MENU( maSections[ nSection ] ), nItemPos );
+//        gchar *aCommand = g_lo_menu_get_action_value_from_item_in_section( pMenu, nSection, nItemPos );
 
-        // Remove empty sections unless section is the last one.
-        if ( g_menu_model_get_n_items( maSections[ nSection ] ) == 0 && maSections.size() > 1 ) {
-            g_lo_menu_remove( G_LO_MENU( mpMenuModel ), nSection );
-            maSections.erase( maSections.begin() + nSection );
-        }
+//        if ( aCommand ) {
+//            GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
+
+//            if ( pActionGroup != NULL )
+//                g_lo_action_group_remove( pActionGroup, aCommand );
+
+//            g_free( aCommand );
+//        }
+
+        cout << __FUNCTION__ << " - " << nSection << " - " << nItemPos << " - " << nPos << " - " << this << endl;
+        g_lo_menu_remove_from_section( pMenu, nSection, nItemPos );
+    }
+    else
+    {
+        gint nSection = g_menu_model_get_n_items( mpMenuModel ) - 1;
+        cout << __FUNCTION__ << " - " << nSection << endl;
+        if ( nSection < 0 )
+            g_lo_menu_remove( pMenu, nSection );
     }
 
     maItems.erase( maItems.begin() + nPos );
@@ -313,23 +340,22 @@ void GtkSalMenu::RemoveItem( unsigned nPos )
 
 void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
 {
+    cout << __FUNCTION__ << endl;
     GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
     GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
 
     if ( pGtkSubMenu == NULL )
         return;
 
+    pGtkSubMenu->mpParentSalMenu = this;
     pItem->mpSubMenu = pGtkSubMenu;
-    g_lo_menu_item_set_submenu( pItem->mpMenuItem, pGtkSubMenu->mpMenuModel );
 
     // Update item in GMenuModel.
     unsigned nSection, nItemPos;
     GetInsertionData( nPos, &nSection, &nItemPos );
 
-    g_lo_menu_remove( G_LO_MENU( maSections[ nSection ] ), nItemPos );
-    g_lo_menu_insert_item( G_LO_MENU( maSections[ nSection ] ), nItemPos, pItem->mpMenuItem );
-
-    pGtkSubMenu->mpParentSalMenu = this;
+    cout << __FUNCTION__ << " - " << nSection << " - " << nItemPos << " - " << nPos << " - " << this << endl;
+    g_lo_menu_set_submenu_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, pGtkSubMenu->mpMenuModel );
 }
 
 void GtkSalMenu::SetFrame( const SalFrame* pFrame )
@@ -345,7 +371,7 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
         GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
 
         if ( pMenu && pActionGroup ) {
-            mpMenuModel = G_MENU_MODEL( pMenu );
+//            mpMenuModel = G_MENU_MODEL( pMenu );
 
             // Merge current action group with the exported one
             g_lo_action_group_clear( pActionGroup );
@@ -355,8 +381,6 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
 
             mpActionGroup = G_ACTION_GROUP( pActionGroup );
         } else {
-            mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
-
             g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", mpMenuModel, ObjectDestroyedNotify );
             g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", mpActionGroup, ObjectDestroyedNotify );
 
@@ -366,6 +390,10 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
             gchar* aDBusWindowPath = g_strdup_printf( "/window/%lu", windowId );
             gchar* aDBusMenubarPath = g_strdup_printf( "/window/%lu/menus/menubar", windowId );
 
+            // Get a DBus session connection.
+            GDBusConnection* pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+            if(!pSessionBus) puts ("Failed to get DBus session connection");
+
             gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) );
             gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "" );
             gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aDBusWindowPath );
@@ -373,24 +401,24 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
 
             // Publish the menu.
             if ( aDBusMenubarPath ) {
-                mMenubarId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, mpMenuModel, NULL);
-                if(!mMenubarId) puts("Fail export menubar");
+                sal_uInt16 menubarId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, mpMenuModel, NULL);
+                if(!menubarId) puts("Failed to export menubar");
             }
 
             if ( aDBusPath ) {
-                mActionGroupId = g_dbus_connection_export_action_group( pSessionBus, aDBusPath, mpActionGroup, NULL);
+                sal_uInt16 actionGroupId = g_dbus_connection_export_action_group( pSessionBus, aDBusPath, mpActionGroup, NULL);
+                if(!actionGroupId) puts("Failed to export action group");
             }
 
             g_free( aDBusPath );
             g_free( aDBusWindowPath );
             g_free( aDBusMenubarPath );
         }
+//        updateNativeMenu( this );
+//        updateNativeMenu( this );
 
-        // Menubar has only one section.
-        g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, maSections[ 0 ] );
-
-        // Refresh the menu every second.
-        // This code is a workaround until required modifications in Gtk+ are available.
+//        // Refresh the menu every second.
+//        // This code is a workaround until required modifications in Gtk+ are available.
         g_timeout_add_seconds( 1, GenerateMenu, this );
     }
 }
@@ -405,27 +433,29 @@ const GtkSalFrame* GtkSalMenu::GetFrame() const
 
 void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
 {
-//    cout << __FUNCTION__ << " - " << nPos << " - " << bCheck << endl;
+//    GtkSalMenuItem* pItem = maItems[ nPos ];
+
+//    if ( pItem->maCommand == NULL || g_strcmp0( pItem->maCommand, "" ) == 0 )
+//        return;
+
 //    GActionGroup* pActionGroup = GetActionGroupFromMenubar( this );
 
 //    if ( !pActionGroup )
 //        return;
 
-//    GtkSalMenuItem* pSalMenuItem = maItems[ nPos ];
 
-//    if ( !pSalMenuItem || pSalMenuItem->mpSubMenu )
+//    if ( !pItem || pItem->mpSubMenu )
 //        return;
 
-//    MenuItemBits itemBits = pSalMenuItem->mnBits;
 //    GVariant *pCheckValue = NULL;
 
-//    if ( itemBits & MIB_CHECKABLE ) {
+//    if ( pItem->mnBits & MIB_CHECKABLE ) {
 //        gboolean bCheckedValue = ( bCheck == sal_True ) ? TRUE : FALSE;
 //        pCheckValue = g_variant_new_boolean( bCheckedValue );
 //    }
 
 //    if ( pCheckValue )
-//        g_action_group_change_action_state( pActionGroup, pSalMenuItem->maCommand, pCheckValue );
+//        g_action_group_change_action_state( pActionGroup, pItem->maCommand, pCheckValue );
 }
 
 void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
@@ -435,49 +465,57 @@ void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
     if ( pActionGroup == NULL )
         return;
 
-    GtkSalMenuItem* pItem = maItems[ nPos ];
-
-    gboolean bItemEnabled = (bEnable == sal_True) ? TRUE : FALSE;
+    sal_uInt16 nId = mpVCLMenu->GetItemId( nPos );
+    rtl::OUString aOUCommand = mpVCLMenu->GetItemCommand( nId );
 
-    if ( pItem->maCommand == NULL || g_strcmp0( pItem->maCommand, "" ) == 0 )
+    if ( aOUCommand == NULL || aOUCommand.isEmpty() )
         return;
 
-    g_lo_action_group_set_action_enabled( pActionGroup, pItem->maCommand, bItemEnabled );
+    gchar* aCommand = (gchar*) rtl::OUStringToOString( aOUCommand, RTL_TEXTENCODING_UTF8 ).getStr();
+
+    gboolean bItemEnabled = (bEnable == sal_True) ? TRUE : FALSE;
+
+    if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bItemEnabled )
+        g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bItemEnabled );
 }
 
 void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText )
 {
     // Replace the "~" character with "_".
     rtl::OUString aText = rText.replace( '~', '_' );
-    rtl::OString aConvertedText = OUStringToOString(aText, RTL_TEXTENCODING_UTF8);
+    rtl::OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
 
-    GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
-    GLOMenuItem *pMenuItem = G_LO_MENU_ITEM( pItem->mpMenuItem );
+//    GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
 
-    unsigned nSection, nInsertPos;
-    GetInsertionData( nPos, &nSection, &nInsertPos );
+    unsigned nSection, nItemPos;
+    GetInsertionData( nPos, &nSection, &nItemPos );
 
-    GLOMenu* pSection = G_LO_MENU( maSections[ nSection ] );
+    cout << __FUNCTION__ << " - " << nSection << " - " << nItemPos << " - " << nPos << " - " << this << " - " << aConvertedText.getStr() << endl;
 
-    GVariant* aCurrentLabel = NULL;
+//    GLOMenu* pSection = G_LO_MENU( maSections[ nSection ] );
 
-    if ( g_menu_model_get_n_items( maSections[ nSection ] ) > 0 )
-        aCurrentLabel = g_menu_model_get_item_attribute_value( G_MENU_MODEL( pSection ), nInsertPos, G_MENU_ATTRIBUTE_LABEL, G_VARIANT_TYPE_STRING );
+//    GVariant* aCurrentLabel = NULL;
 
-    sal_Bool bSetLabel = sal_True;
+//    if ( g_menu_model_get_n_items( maSections[ nSection ] ) > nInsertPos )
+//        aCurrentLabel = g_menu_model_get_item_attribute_value( G_MENU_MODEL( pSection ), nInsertPos, G_MENU_ATTRIBUTE_LABEL, G_VARIANT_TYPE_STRING );
 
-    if ( aCurrentLabel != NULL ) {
-        if ( g_strcmp0( g_variant_get_string( aCurrentLabel, NULL ), aConvertedText.getStr() ) == 0 ) {
-            bSetLabel = sal_False;
-        }
-    }
+//    sal_Bool bSetLabel = sal_True;
 
-    if ( bSetLabel == sal_True ) {
-        g_lo_menu_item_set_label( pMenuItem, aConvertedText.getStr() );
+//    if ( aCurrentLabel != NULL ) {
+//        if ( g_strcmp0( g_variant_get_string( aCurrentLabel, NULL ), aConvertedText.getStr() ) == 0 ) {
+//            bSetLabel = sal_False;
+//        }
+//    }
 
-        g_lo_menu_remove( pSection, nInsertPos );
-        g_lo_menu_insert_item( pSection, nInsertPos, pItem->mpMenuItem );
-    }
+//    if ( bSetLabel == sal_True ) {
+        g_lo_menu_set_label_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
+
+////        cout << __FUNCTION__ << " - " << aConvertedText.getStr() << " - Section: " << nSection << " - Position: " << nInsertPos << " - Section size: " << g_menu_model_get_n_items( G_MENU_MODEL( pSection ) ) << endl;
+//        if ( g_menu_model_get_n_items( G_MENU_MODEL( pSection ) ) > nInsertPos )
+//            g_lo_menu_remove( pSection, nInsertPos );
+
+//        g_lo_menu_insert_item( pSection, nInsertPos, pItem );
+//    }
 }
 
 void GtkSalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage)
@@ -486,63 +524,98 @@ void GtkSalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const I
 
 void GtkSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const rtl::OUString& rKeyName )
 {
-    //    GtkSalMenuItem *pGtkSalMenuItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
+//    GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
+
+//    if ( rKeyName.isEmpty() )
+//        return;
 
-    //    if ( rKeyName.isEmpty() )
-    //        return;
+//    rtl::OString aAccelerator = rtl::OUStringToOString( GetGtkKeyName( rKeyName ), RTL_TEXTENCODING_UTF8 );
 
-    //    rtl::OString aAccelerator = rtl::OUStringToOString( GetGtkKeyName( rKeyName ), RTL_TEXTENCODING_UTF8 );
+//    unsigned nSection, nItemPos;
+//    GetInsertionData( nPos, &nSection, &nItemPos );
 
-    //    GVariant* aCurrentAccel = g_menu_model_get_item_attribute_value( pGtkSalMenuItem->mpParentSection, pGtkSalMenuItem->mnPos, "accel", G_VARIANT_TYPE_STRING );
+//    GLOMenu* pSection = G_LO_MENU( maSections[ nSection ] );
 
-    //    sal_Bool bSetAccel = sal_True;
+//    GVariant* aCurrentAccel = g_menu_model_get_item_attribute_value( G_MENU_MODEL( pSection ), nItemPos, "accel", G_VARIANT_TYPE_STRING );
 
-    //    if ( aCurrentAccel ) {
-    //        if ( g_strcmp0( g_variant_get_string( aCurrentAccel, NULL ), aAccelerator.getStr() ) == 0 ) {
-    //            bSetAccel = sal_False;
-    //        }
-    //    }
+//    sal_Bool bSetAccel = sal_True;
 
-    //    if ( bSetAccel == sal_True ) {
-    //        g_lo_menu_item_set_attribute_value( pGtkSalMenuItem->mpMenuItem, "accel", g_variant_new_string( aAccelerator.getStr() ) );
+//    if ( aCurrentAccel ) {
+//        if ( g_strcmp0( g_variant_get_string( aCurrentAccel, NULL ), aAccelerator.getStr() ) == 0 ) {
+//            bSetAccel = sal_False;
+//        }
+//    }
 
-    //        g_lo_menu_remove( G_LO_MENU( pGtkSalMenuItem->mpParentSection), pGtkSalMenuItem->mnPos );
-    //        g_lo_menu_insert_item( G_LO_MENU( pGtkSalMenuItem->mpParentSection ), pGtkSalMenuItem->mnPos, pGtkSalMenuItem->mpMenuItem );
-    //    }
+//    if ( bSetAccel == sal_True ) {
+//        g_lo_menu_item_set_attribute_value( pItem->mpMenuItem, "accel", g_variant_new_string( aAccelerator.getStr() ) );
+
+//        g_lo_menu_remove( pSection, nItemPos );
+//        g_lo_menu_insert_item( pSection, nItemPos, pItem );
+//    }
 }
 
 void GtkSalMenu::SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr )
 {
     GtkSalMenuItem* pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
 
-    if ( pItem->mpMenuItem ) {
-        rtl::OString aOCommandStr = rtl::OUStringToOString( aCommandStr, RTL_TEXTENCODING_UTF8 );
+    if ( pItem->mnType == MENUITEM_SEPARATOR || pItem->mpVCLMenu->GetPopupMenu( pItem->mnId ) != NULL )
+        return;
+
+    gchar* aCommand = (gchar*) rtl::OUStringToOString( aCommandStr, RTL_TEXTENCODING_UTF8 ).getStr();
 
-        if ( pItem->maCommand )
-            g_free( pItem->maCommand );
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
+    if ( pActionGroup == NULL )
+        return;
 
-        pItem->maCommand = g_strdup( aOCommandStr.getStr() );
+//    gboolean bChecked = ( pItem->mpVCLMenu->IsItemChecked( pItem->mnId ) ) ? TRUE : FALSE;
 
-        GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
-        if ( pActionGroup ) {
-            g_lo_action_group_insert( pActionGroup, pItem->maCommand, pItem );
-        }
+//    if ( pItem->mnBits & MIB_CHECKABLE )
+//    {
+////        cout << "Item with command: " << pItem->maCommand << " is checkmark button." << endl;
 
-        if ( pItem->mpVCLMenu->GetPopupMenu( pItem->mnId ) == NULL ) {
-            gchar* aItemCommand = g_strconcat("win.", pItem->maCommand, NULL );
+//        // Item is a checkmark button.
+//        GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
+//        GVariant* pState = g_variant_new_boolean( bChecked );
 
-            g_lo_menu_item_set_action_and_target( pItem->mpMenuItem, aItemCommand, NULL );
+//        g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem, NULL, pStateType, NULL, pState );
+//    }
+//    else if ( pItem->mnBits & MIB_RADIOCHECK )
+//    {
+////        cout << "Item with command: " << pItem->maCommand << " is a radio button." << endl;
 
-            g_free( aItemCommand );
+//        // Item is a radio button.
+////        GVariantType* pParameterType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
+////        GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
+//        //        GVariant* pStateHint = GetRadionButtonHints( pItem );
+////        GVariant* pState = g_variant_new_string( "" );
 
-            unsigned nSection, nInsertPos;
-            GetInsertionData( nPos, &nSection, &nInsertPos );
+////        g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem, pParameterType, pStateType, NULL, pState );
+//    }
+//    else
+//    {
+        // Item is not special, so insert a stateless action.
+        g_lo_action_group_insert( pActionGroup, aCommand, pItem );
+//    }
 
-            GLOMenu* pSection = G_LO_MENU( maSections[ nSection ] );
-            g_lo_menu_remove( pSection, nInsertPos );
-            g_lo_menu_insert_item( pSection, nInsertPos, pItem->mpMenuItem );
-        }
-    }
+    // Menu item is not updated unless it's necessary.
+//    if ( ( pItem->maCommand != NULL ) && ( g_strcmp0( pItem->maCommand, aCommand ) == 0 ) )
+//        return;
+
+//    if ( pItem->maCommand != NULL )
+//        g_free( pItem->maCommand );
+
+//    pItem->maCommand = g_strdup( aCommand );
+
+        unsigned nSection, nItemPos;
+        GetInsertionData( nPos, &nSection, &nItemPos );
+
+        cout << __FUNCTION__ << " - " << nSection << " - " << nItemPos << " - " << nPos << " - " << this << endl;
+
+    gchar* aItemCommand = g_strconcat("win.", aCommand, NULL );
+
+    g_lo_menu_set_action_and_target_value_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aItemCommand, NULL );
+
+    g_free( aItemCommand );
 }
 
 void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData )
@@ -562,37 +635,16 @@ void GtkSalMenu::Freeze()
 GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
     mnId( pItemData->nId ),
     mnBits( pItemData->nBits ),
-    maCommand( NULL ),
+    mnType( pItemData->eType ),
     mpVCLMenu( pItemData->pMenu ),
     mpParentMenu( NULL ),
-    mpSubMenu( NULL ),
-    mpMenuItem( NULL ),
-    mpStateType( NULL ),
-    mpState( NULL )
+    mpSubMenu( NULL )
 {
-    if ( pItemData->eType != MENUITEM_SEPARATOR ) {
-        mpMenuItem = g_lo_menu_item_new( "EMPTY STRING", NULL );
-
-        rtl::OUString aCommand = mpVCLMenu->GetItemCommand( mnId );
-
-        if ( aCommand == NULL || aCommand.isEmpty() == sal_True )
-            return;
-
-        maCommand = g_strdup( rtl::OUStringToOString( aCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
-        gchar* aActionCommand = g_strconcat( "win.", maCommand, NULL );
-
-        g_lo_menu_item_set_action_and_target( mpMenuItem, aActionCommand, NULL );
-
-        g_free( aActionCommand );
-    }
 }
 
 GtkSalMenuItem::~GtkSalMenuItem()
 {
-    if ( mpMenuItem ) {
-        g_object_unref( mpMenuItem );
-
-        if ( maCommand )
-            g_free( maCommand );
-    }
+//    mpVCLMenu = NULL;
 }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 38ffbf61cf7e68adcae1b1ade95a26812fa61712
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Tue Aug 21 15:03:30 2012 +0100

    Items are not duplicated anymore, but launching a new instance crashes.
    
    Change-Id: Ib3966c8578b0c4695c1f2cea89c3df234f597922

diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index c57d39d..9332cb6 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -62,11 +62,11 @@ private:
 
     // GMenuModel and GActionGroup attributes
     GMenuModel*                     mpMenuModel;
-    GMenuModel*                     mpCurrentSection;
     GActionGroup*                   mpActionGroup;
 
     GtkSalMenuItem* GetSalMenuItem( sal_uInt16 nId );
-    sal_Int16      GetSectionNumber( GMenuModel* pSection );
+    sal_Int16       GetSectionNumber( GMenuModel* pSection );
+    void            GetInsertionData( unsigned nPos, unsigned *insertSection, unsigned *insertPos );
 
 public:
     GtkSalMenu( sal_Bool bMenuBar );
@@ -93,7 +93,7 @@ public:
     virtual Menu*               GetMenu() { return mpVCLMenu; }
     virtual GtkSalMenu*         GetParentSalMenu() { return mpParentSalMenu; }
     virtual GMenuModel*         GetMenuModel() { return mpMenuModel; }
-    virtual GMenuModel*         GetCurrentSection() { return mpCurrentSection; }
+//    virtual GMenuModel*         GetCurrentSection() { return mpCurrentSection; }
     virtual unsigned            GetItemCount() { return maItems.size(); }
     virtual GtkSalMenuItem*     GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
     virtual GActionGroup*       GetActionGroup() { return mpActionGroup; }
@@ -107,7 +107,6 @@ public:
 
     sal_uInt16          mnId;               // Item ID
     MenuItemBits        mnBits;             // Item bits
-    sal_uInt16          mnPos;              // Item position
     gchar*              maCommand;          // Item command
     Menu*               mpVCLMenu;          // VCL Menu into which this MenuItem is inserted
     GtkSalMenu*         mpParentMenu;       // The menu in which this menu item is inserted
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index d682fbe..7e0004a 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -36,30 +36,36 @@ isSpecialSubmenu (OUString command)
 }
 
 void updateNativeMenu( GtkSalMenu* pMenu ) {
-    if ( pMenu ) {
-        for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ ) {
-            GtkSalMenuItem* pSalMenuItem = pMenu->GetItemAtPos( i );
+    if ( pMenu == NULL )
+        return;
 
-            if ( !pSalMenuItem->mpVCLMenu )
-                continue;
+    for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ ) {
+        GtkSalMenuItem* pSalMenuItem = pMenu->GetItemAtPos( i );
 
-            String aText = pSalMenuItem->mpVCLMenu->GetItemText( pSalMenuItem->mnId );
+        Menu* pVCLMenu = pSalMenuItem->mpVCLMenu;
 
-            // Force updating of native menu labels.
-            pMenu->SetItemText( i, pSalMenuItem, aText );
+        if ( pVCLMenu == NULL )
+            continue;
 
-            KeyCode nAccelKey = pSalMenuItem->mpVCLMenu->GetAccelKey( pSalMenuItem->mnId );
-            pMenu->SetAccelerator( i, pSalMenuItem, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+        sal_uInt16 nId = pSalMenuItem->mnId;
 
-            if ( isSpecialSubmenu( rtl::OUString::createFromAscii( pSalMenuItem->maCommand ) ) == FALSE ) {
-                if ( pSalMenuItem->mpSubMenu && pSalMenuItem->mpSubMenu->GetMenu() ) {
-                    pSalMenuItem->mpSubMenu->GetMenu()->Activate();
-                    // FIXME: Using Deactivate() let the menu to update itself correctly, but generates
-                    // duplicated popup menus.
-                    pSalMenuItem->mpSubMenu->GetMenu()->Deactivate();
-                    updateNativeMenu( pSalMenuItem->mpSubMenu );
-                }
-            }
+        String aText = pVCLMenu->GetItemText( nId );
+        sal_Bool itemEnabled = pVCLMenu->IsItemEnabled( nId );
+
+        // Force updating of native menu labels.
+        pMenu->SetItemText( i, pSalMenuItem, aText );
+
+        pMenu->EnableItem( i, itemEnabled );
+
+        //            KeyCode nAccelKey = pSubmenu->GetAccelKey( pSalMenuItem->mnId );
+        //            pMenu->SetAccelerator( i, pSalMenuItem, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+
+        GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
+
+        if ( pSubmenu && pSubmenu->GetMenu() ) {
+            pSubmenu->GetMenu()->Activate();
+            updateNativeMenu( pSubmenu );
+            pSubmenu->GetMenu()->Deactivate();
         }
     }
 }
@@ -180,6 +186,26 @@ sal_Int16 GtkSalMenu::GetSectionNumber( GMenuModel* pSection )
     return -1;
 }
 
+void GtkSalMenu::GetInsertionData( unsigned nPos, unsigned *insertSection, unsigned *insertPos )
+{
+    unsigned nItems;
+    unsigned nSection;
+
+    for ( nSection = 0, nItems = 0; nSection < maSections.size(); nSection++ )
+    {
+        if ( nPos <= nItems + g_menu_model_get_n_items( maSections[ nSection ] ) ) {
+            *insertSection = nSection;
+            *insertPos = nPos - nItems;
+            return;
+        }
+
+        nItems += g_menu_model_get_n_items( maSections[ nSection ] ) + 1;    // +1 to count the separator.
+    }
+
+    *insertSection = maSections.size() - 1;
+    *insertPos = MENU_APPEND;
+}
+
 GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mbMenuBar( bMenuBar ),
     mpVCLMenu( NULL ),
@@ -191,8 +217,8 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mpMenuModel( NULL ),
     mpActionGroup( NULL )
 {
-    mpCurrentSection = G_MENU_MODEL( g_lo_menu_new() );
-    maSections.push_back( mpCurrentSection );
+    GMenuModel* pSection = G_MENU_MODEL( g_lo_menu_new() );
+    maSections.push_back( pSection );
 
     if (bMenuBar) {
         mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new() );
@@ -201,7 +227,7 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
         if(!pSessionBus) puts ("Fail bus get");
     } else {
         mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
-        g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
+        g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, pSection );
     }
 }
 
@@ -209,8 +235,6 @@ GtkSalMenu::~GtkSalMenu()
 {
     g_source_remove_by_user_data( this );
 
-    g_object_unref( mpCurrentSection );
-
     if ( mbMenuBar ) {
         g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
         mpMenuModel = NULL;
@@ -235,82 +259,77 @@ sal_Bool GtkSalMenu::VisibleMenuBar()
 
 void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
 {
-    GtkSalMenuItem *pGtkSalMenuItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
-
-    maItems.push_back( pGtkSalMenuItem );
+    GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
 
-    if ( pGtkSalMenuItem->mpMenuItem ) {
-        if ( !mpCurrentSection ) {
-            mpCurrentSection = G_MENU_MODEL( g_lo_menu_new() );
-            maSections.push_back( mpCurrentSection );
+    if ( nPos == MENU_APPEND ) {
+        maItems.push_back( pItem );
+    } else {
+        maItems.insert( maItems.begin() + nPos, pItem );
+    }
 
-            if ( mpMenuModel ) {
-                g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
-            }
-        }
+    if ( pItem->mpMenuItem ) {
+        unsigned nSection, nInsertPos;
 
-        pGtkSalMenuItem->mpParentSection = mpCurrentSection;
-        pGtkSalMenuItem->mnPos = g_menu_model_get_n_items( mpCurrentSection );
+        // Get the section number and position to insert the item.
+        GetInsertionData( nPos, &nSection, &nInsertPos );
 
-        g_lo_menu_insert_item( G_LO_MENU( mpCurrentSection ), pGtkSalMenuItem->mnPos, pGtkSalMenuItem->mpMenuItem );
+        g_lo_menu_insert_item( G_LO_MENU( maSections[ nSection ] ), nInsertPos, pItem->mpMenuItem );
     } else {
         // If no mpMenuItem exists, then item is a separator.

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list