I am trying to write a GTK 4 app in C language. I want to make a callback function that reacts to item chosen from a dropdown widget and updates the entry widget with the value of selected item.
My function works only if I make entry widget a global variable and use it directly in the function. I would prefer to pass a pointer to that widget and make callback function modify it this way. Other functions that were passed pointers to widgets worked, but this one doesn’t want to.
//main.c
#include <gtk/gtk.h>
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include "uiElements.h"
static void baudrateDropdownSelectCallback(GtkDropDown *dropdown, void *data[]);
static void activateApp(GApplication *app);
int main (int argc, char *argv[]) {
//starting application
return startApp("exe.GTKforSO", G_APPLICATION_DEFAULT_FLAGS, activateApp, argc, argv);
}
static void activateApp (GApplication *app) {
static GtkWidget *win;
static GtkWidget *box;
//window
win=initWindow(app, "GTKforSO", 400, 200);
//box
box=initBox(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child(GTK_WINDOW(win), box);
static GtkWidget *baudrateDropdown;
static GtkWidget *baudratesBox;
static GtkWidget *baudrateEntry;
static GtkEntryBuffer *baudrateEntryBuffer;
/** the important part **/
baudratesBox=initBox(GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_append(GTK_BOX(box), baudratesBox);
char *baudrates[]={"50", "75", "110", "134",
"150", "200", "300", "600", "1200", "1800",
"2400", "4800", "9600", "19200", "28800",
"38400", "57600", "76800", "115200", "230400",
"460800", "576000", "921600", NULL};
baudrateDropdown=initDropDown(baudrates, 18); //dropdown widget with 'baudrates' list of items and 18th item selected
gtk_box_append(GTK_BOX(baudratesBox), baudrateDropdown);
void *selectedItem=gtk_drop_down_get_selected_item(GTK_DROP_DOWN(baudrateDropdown)); //getting selected item from dropdown widget
const char *selectedBaudrate=gtk_string_object_get_string(GTK_STRING_OBJECT(selectedItem)); //getting item value as string
baudrateEntryBuffer=gtk_entry_buffer_new((const char*)selectedBaudrate, strlen(selectedBaudrate)); //new entry buffer widget
baudrateEntry=gtk_entry_new_with_buffer(GTK_ENTRY_BUFFER(baudrateEntryBuffer)); //new entry widget with buffer 'baudrateEntryBuffer'
void *entryAndBuffer[2]={baudrateEntry, baudrateEntryBuffer}; //data to pass to callback
g_signal_connect(baudrateDropdown, "notify::selected-item", G_CALLBACK(baudrateDropdownSelectCallback), entryAndBuffer); //connection to callback
gtk_box_append(GTK_BOX(baudratesBox), baudrateEntry);
/**/
gtk_window_present(GTK_WINDOW(win));
}
static void baudrateDropdownSelectCallback(GtkDropDown *dropdown, void *data[]) {
void *newlySelectedItem=gtk_drop_down_get_selected_item(GTK_DROP_DOWN(dropdown)); //getting selected item from dropdown widget
char *selected=gtk_string_object_get_string(GTK_STRING_OBJECT(newlySelectedItem)); //getting item value as string
GtkEntryBuffer *buffer;
buffer=gtk_entry_buffer_new(selected, strlen(selected));
data[1]=buffer; //replacing old buffer with new one
gtk_entry_set_buffer(GTK_ENTRY(data[0]), data[1]); //this doesn't work
//gtk_entry_set_buffer(GTK_ENTRY(baudrateEntry), data[1]); //this works if static GtkWidget *baudrateEntry; is global variable
}
//uiElements.h
#ifndef UI_ELEMENTS_H
#define UI_ELEMENTS_H
#include <gtk/gtk.h>
typedef enum {
NO_ENTRY=0,
WITH_ENTRY=1
} withEntry;
int startApp(char *id, GApplicationFlags flags, void (*activateFunc), int argc, char *argv[]);
GtkWidget *initWindow(GApplication *app, char *windowTitle, int windowWidth, int windowHeight);
GtkWidget *initBox(GtkOrientation orientation, int spacing);
GtkWidget *initDropDown(char *list[], uint8_t selectedByDefault);
#endif /* UI_ELEMENTS_H */
//uiElements.c
#include "uiElements.h"
int startApp(char *id, GApplicationFlags flags, void (*activateFunc), int argc, char *argv[]) {
GtkApplication *app;
int stat;
app=gtk_application_new(id, flags);
g_signal_connect(app, "activate", G_CALLBACK(activateFunc), NULL);
stat=g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return stat;
}
GtkWidget *initWindow(GApplication *app, char *windowTitle, int windowWidth, int windowHeight) {
GtkWidget *win;
win=gtk_application_window_new(GTK_APPLICATION(app));
gtk_window_set_title(GTK_WINDOW(win), windowTitle);
gtk_window_set_default_size(GTK_WINDOW(win), windowWidth, windowHeight);
return win;
}
GtkWidget *initBox(GtkOrientation orientation, int spacing) {
GtkWidget *box;
box=gtk_box_new(orientation, spacing);
gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
return box;
}
GtkWidget *initDropDown(char *list[], uint8_t selectedByDefault) {
GtkStringList *stringList=gtk_string_list_new((const char * const *)list);
GtkWidget *dropdown;
dropdown=gtk_drop_down_new(G_LIST_MODEL(stringList), NULL);
gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), selectedByDefault);
return(dropdown);
}