0

to build a clean GTK4 version of my program (https://atomes.ipcms.fr) I need to be able to add pango markup in GTK4 menus, and, the menu(s) must be C coded and not read from XML file(s).

This question follows the one from this post (that contains a visual illustration):

https://discourse.gnome.org/t/gtk4-menus-and-pango-markup/8828

A little bit more than a year ago I asked the same thing, got answers, waited for a long time for updates in the GTK4 lib, hopping for the answer to work at some point ... and no ...

Basically it works when reading the menu from a XML file, and it does not when coding directly the menu elements, and I really, really, must do it this way.

Here is a piece of example code I wrote:

#include <gtk/gtk.h>

GtkApplication * TestApp = NULL;

void menu_bar_action (GSimpleAction * action, GVariant * parameter, gpointer data)
{
  gchar * name = g_strdup_printf ("%s", g_action_get_name(G_ACTION(action)));
  if (g_strcmp0 (name, "quit") == 0)
  {
    g_application_quit (G_APPLICATION(TestApp));
  }
}

GMenuItem * create_gmenu_item (const gchar * label, const gchar * action)
{
  GMenuItem * item;
  item = g_menu_item_new (label, action);
  // Requesting to use markup here:
  g_menu_item_set_attribute (item, "use-markup", "b", TRUE, NULL);
  return item;
}

void append_menu_item (GMenu * menu, const gchar * label, const gchar * action)
{
  GMenuItem * item = create_gmenu_item (label, action);
  g_menu_append_item (menu, item);
  g_object_unref (item);
}

void run_program (GApplication * app, gpointer data)
{
  GtkWidget * window = gtk_application_window_new (GTK_APPLICATION(app));
  gtk_window_set_title (GTK_WINDOW(window), "Test");
  gtk_window_set_resizable (GTK_WINDOW(window), TRUE);
  gtk_widget_set_size_request (window, 900, 450);

#ifdef UIMODE
  GtkBuilder * builder = gtk_builder_new ();
  gtk_builder_add_from_file (builder, "test.ui", NULL);
  gtk_application_set_menubar (GTK_APPLICATION (app),
                               G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
  g_object_unref (builder);
#else
  GMenu * menubar = g_menu_new();
  GMenu * menu    = g_menu_new ();
  // Trying different things just in case:
  append_menu_item (menu, "C(H)<sub>2</sub>", "None");
  append_menu_item (menu, "C(H)&lt;sub&gt;3&lt;/sub&gt;", "None");
  append_menu_item (menu, "C(H)<sub>4</sub>", "None");
  append_menu_item (menu, "Quit", "app.quit");
    
  g_menu_append_submenu (menubar, "File", G_MENU_MODEL (menu));
  g_object_unref (menu);
    
  gtk_application_set_menubar (GTK_APPLICATION(app), G_MENU_MODEL(menubar));
#endif  
  GSimpleAction * act = g_simple_action_new ("quit", NULL);
  g_signal_connect (act, "activate", G_CALLBACK(menu_bar_action), NULL);
  g_action_map_add_action (G_ACTION_MAP(GTK_APPLICATION(app)), G_ACTION(act)); 
  gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW(window), TRUE);
  gtk_window_present (GTK_WINDOW(window)); 
}

int main (int argc, char *argv[])
{
  // setlocale(LC_ALL,"en_US");
  gtk_disable_setlocale ();
  TestApp = gtk_application_new (g_strdup_printf ("test._%d.gtk", (int)clock()), G_APPLICATION_DEFAULT_FLAGS);
  g_signal_connect (G_OBJECT(TestApp), "activate", G_CALLBACK(run_program), NULL);
  int status = g_application_run (G_APPLICATION (TestApp), 0, NULL);
  g_object_unref (TestApp);
  return status;
}

And the 'test.ui' optional XML file for the menu:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <menu id="menubar">
    <submenu>
      <attribute name="label" translatable="yes">Test</attribute>
      <section>
        <item>
      <attribute name="label" translatable="yes">C(H)&lt;sub&gt;2&lt;/sub&gt;</attribute>
          <attribute name="use-markup">TRUE</attribute>
          <attribute name="action">None</attribute>
        </item>
        <item>
      <attribute name="label" translatable="yes">C(H)&lt;sub&gt;3&lt;/sub&gt;</attribute>
          <attribute name="use-markup">TRUE</attribute>
          <attribute name="action">None</attribute>
        </item>
        <item>
      <attribute name="label" translatable="yes">C(H)&lt;sub&gt;3&lt;/sub&gt;</attribute>
          <attribute name="use-markup">TRUE</attribute>
          <attribute name="action">None</attribute>
        </item>
        <item>
      <attribute name="label" translatable="yes">Quit</attribute>
          <attribute name="action">app.quit</attribute>
        </item>
      </section>
    </submenu>
  </menu>
</interface>

If I build the code using:

#!/bin/bash

app=$1

LIBS="-Wl,--export-dynamic `pkg-config --libs gtk4`"
INCLUDES="`pkg-config --cflags gtk4`"
CFLAGS="-O2"
gcc -o $app'.x' $CFLAGS $INCLUDES $app'.c' $LIBS -DUIMODE

Then the menu, loaded from the XML file properly uses pango markup.

However If I build the code using:

#!/bin/bash

app=$1

LIBS="-Wl,--export-dynamic `pkg-config --libs gtk4`"
INCLUDES="`pkg-config --cflags gtk4`"
CFLAGS="-O2"
gcc -o $app'.x' $CFLAGS $INCLUDES $app'.c' $LIBS

Then no markup.

I tested this on a clean, all new Debian 12, with GTK 4.8.3.

You will understand based on my examples that I want to display chemical formula.

Thanks in advance if you have any ideas to help !

Best regards ;-)

1 Answers1

0

Not submit a boolean but a string as attribute does the trick.

Instead of:

gmenu_item_set_attribute (item, "use-markup", "b", TRUE, NULL);

Use:

gmenu_item_set_attribute (item, "use-markup", "s", "TRUE", NULL);