skip to Main Content

I want to use font dialog on gtk4. This is how I did it for gtk3 using GtkFontChooserDialog–

static gboolean filter_font_cb (const PangoFontFamily *family,
                                const PangoFontFace   *face,
                                gpointer               data)
{
   const char *alias_families[] = {
     "DejaVu Sans Mono",
     "FreeMono",
     "Liberation Mono",
     "Mitra",
     "Monospace",
     "Nimbus Mono PS",
     "Noto Mono",
     "Tlwg Mono",
     "Tlwg Typo",
     "Ubuntu Mono",
     NULL
   };
   const char *family_name;

   family_name = pango_font_family_get_name (PANGO_FONT_FAMILY (family));

   return g_strv_contains (alias_families, family_name);
}
void select_font(GtkWidget *widget, gpointer data) {

  GtkResponseType result;

  GtkWidget *dialog = gtk_font_chooser_dialog_new("Select Font", (GtkWindow *)preferences);

  gtk_font_chooser_set_font ((GtkFontChooser   *)dialog, data);

  gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (dialog), filter_font_cb, NULL, NULL);

  result = gtk_dialog_run(GTK_DIALOG(dialog));

  if (result == GTK_RESPONSE_OK || result == GTK_RESPONSE_APPLY) {

      gchar *fontname = gtk_font_chooser_get_font((GtkFontChooser *)dialog);

      printf("%sn", fontname);

      g_free(fontname);
   }
  gtk_widget_destroy(dialog);
}

But since gtk 4.10 GtkFontChooserDialog is Deprecated. It has been replaced with GtkFontDialog. Can someone tell me how to implement GtkFontDialog?

On gtk4 i tried this way but unable to filter font–

GtkFontDialog *fontDialog = gtk_font_dialog_new ();
GtkWidget *fontButton = gtk_font_dialog_button_new(fontDialog);

2

Answers


  1. Gtk4 has the claim to work object-oriented and with lists.
    Accordingly, the fonts of GtkFontDialog are represented as GtkFilterListModel. So if you only want to show one selection, you need a GtkFilter. Since GtkFilter is an abstract class, you have to derive your own and implement the filter criteria there. For this purpose, the function ‘match’ is overwritten, which iterated with the parameter "item" over all fonds passed by GtkFontDialog.
    "item" is passed as PangoFondFace.A return value of TRUE means: the fond is displayed. FALSE, it will not be displayed.

    A simple variant can look like this:

    class-font-filter.h

     
    #pragma once
    #include<gtk/gtk.h>
    
    #define  FONT_TYPE_FILTER (font_filter_get_type())
     
    G_DECLARE_FINAL_TYPE (FontFilter, font_filter,  FONT, FILTER, GtkFilter)
     
    GtkFilter *font_filter_new();
    
    

    class-font-filter.c

    #include"class-font-filter.h"
    
    struct _FontFilter
    {
      GtkFilter parent_instance;
    };
     
    struct _FontFilterClass
    {
      GtkFilterClass parent_class;
    };
     
    G_DEFINE_TYPE (FontFilter, font_filter, GTK_TYPE_FILTER)
     
    static void
    font_filter_init(FontFilter *self)
    {
    }
     
    gboolean font_filter_match (GtkFilter *self, gpointer item )
    {
        PangoFontFace * face =(PANGO_FONT_FACE(item));
        const char *font_name = pango_font_face_get_face_name(face);
        PangoFontFamily *family = pango_font_face_get_family(face);
        const char *family_name = pango_font_family_get_name(family);
    
        if (strcmp(family_name, "Ubuntu") == 0 && strcmp(font_name, "Regular") == 0 )
                 return TRUE; 
        else  if (strcmp(family_name, "FreeMono") == 0 && strcmp(font_name, "Regular") == 0 )
            return TRUE;
        else if (strcmp(family_name, "Mitra") == 0)
             return TRUE;
         else
                 return FALSE;
    
    }
    
    
    
    static void
    font_filter_class_init (FontFilterClass *class)
    {
            GTK_FILTER_CLASS(class)->match = font_filter_match;
    }
     
    GtkFilter *
    font_filter_new ()
    {
    FontFilter *self;
     
      self = g_object_new (FONT_TYPE_FILTER,NULL);
    
      return GTK_FILTER (self);
     }
    

    This is then integrated into the program:

    font-dialog.h

    #include<gtk/gtk.h>
    
    void activate(GtkApplication *app, gpointer data);
    
    

    font-dialog.c

     
    #include"font-dialog.h"
    #include"class-font-filter.h"
    
    void chow_font(GtkWidget *f_button)
    {
     PangoFontDescription* fontdescription = gtk_font_dialog_button_get_font_desc (GTK_FONT_DIALOG_BUTTON(f_button));
    
     char* font = pango_font_description_to_string (fontdescription); 
     
     g_print ("The selectet fond is:  %sn",font); 
    
    }
    
    void activate (GtkApplication *app, gpointer data)
    {
      GtkWidget *window;
    
      window =gtk_application_window_new(app);
      gtk_widget_set_size_request(window,50,50);
     
      GtkFontDialog* fontdialog = gtk_font_dialog_new ();
    
      GtkWidget* f_button = gtk_font_dialog_button_new (fontdialog);
    
      g_signal_connect(f_button,"notify::font-desc", G_CALLBACK(chow_font),NULL);
     
      GtkFilter* filter = font_filter_new();
    
      gtk_font_dialog_set_filter ( fontdialog, GTK_FILTER(filter));
    
      gtk_window_set_child(GTK_WINDOW(window),f_button);
     
     gtk_widget_set_visible(window,TRUE);
    }
    
    

    And the completeness sake:

    main-font-dialog.c

    #include"font-dialog.h"
    
    int
    main (int argc, char **argv)
    {
      GtkApplication *app;
      int status;
    
      app = gtk_application_new ("holger.gtk.font-dialog", G_APPLICATION_DEFAULT_FLAGS);
      g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
      status = g_application_run (G_APPLICATION (app), argc, argv);
      g_object_unref (app);
    
      return status;
    }
    

    If you want to make it a little more elaborate, you can also put the fonts to be selected in a list, which is then given when the class FontFilter is initiated.Of course, then, the function font-filter-match(…)
    be adjusted accordingly.

    But the principle should have become clear.

    Alternatively, there is also the possibility to write an own PangoFontMap class, which can then also be derived from the corresponding abstract class. Their object instance can then be used with gtk-font-dialog-set-font-map() to be made available to the GtkFond dialog.

    Have fun experimenting.

    enter image description here

    Login or Signup to reply.
  2. Since I am interested in the matter itself, I searched and experimented a little. In fact, there is a simpler way to provide the selection for the GtkFondDialog.For this purpose, Gtk4 offers the GtkCustomFilter, i.e. a filter object, which has already been derived from GtkFilter.

    In my opinion, this makes it even easier than with Gtk3.

    Here the code:

    #include"custom-filter.h"
    
    void chow_font(GtkWidget *f_button)
    {
     PangoFontDescription* fontdescription = gtk_font_dialog_button_get_font_desc (GTK_FONT_DIALOG_BUTTON(f_button));
    
     char* font = pango_font_description_to_string (fontdescription); 
     
     g_print ("The selectet fond is:  %sn",font); 
    
    }
    
     gboolean match_func(GObject *item,void *data)
     {
       const char *alias_families[] = {
         "DejaVu Sans Mono",
         "FreeMono",
         "Liberation Mono",
         "Mitra",
         "Monospace",
         "Nimbus Mono PS",
         "Noto Mono",
         "Tlwg Mono",
         "Tlwg Typo",
         "Ubuntu Mono",
         NULL
       };
       const char *family_name;
       PangoFontFace * face =(PANGO_FONT_FACE(item));
       const char *font_name = pango_font_face_get_face_name(face);
       PangoFontFamily *family = pango_font_face_get_family(face);
       family_name = pango_font_family_get_name (PANGO_FONT_FAMILY (family));
    
       return g_strv_contains (alias_families, family_name);
     
    }
     
    void activate (GtkApplication *app, gpointer data)
    {
      GtkWidget *window;
    
      window =gtk_application_window_new(app);
      gtk_widget_set_size_request(window,50,50);
     
      GtkFontDialog* fontdialog = gtk_font_dialog_new ();
    
      GtkWidget* f_button = gtk_font_dialog_button_new (fontdialog);
    
      PangoFontDescription* font_description =  pango_font_description_from_string ("DejaVu Sans Mono 15"); 
    
      gtk_font_dialog_button_set_font_desc ((GtkFontDialogButton*) f_button, font_description);
      
      g_signal_connect(f_button,"notify::font-desc", G_CALLBACK(chow_font),NULL);
     
      GtkCustomFilter* filter = gtk_custom_filter_new ((GtkCustomFilterFunc) match_func, NULL,NULL);
      
      gtk_font_dialog_set_filter ( fontdialog, GTK_FILTER(filter));
    
      gtk_window_set_child(GTK_WINDOW(window),f_button);
     
     gtk_widget_set_visible(window,TRUE);
    }
    
    

    Have fun programming with GTK4

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search